lire-2.1.1/0000755000175000017500000000000011677607766007476 500000000000000lire-2.1.1/all/0000755000175000017500000000000011677607766010246 500000000000000lire-2.1.1/all/po/0000755000175000017500000000000011677607770010657 500000000000000lire-2.1.1/all/po/lire.pot0000644000175000017500000017341611677606225012264 00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Stichting LogReport Foundation # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: bugs@logreport.org\n" "POT-Creation-Date: 2011-12-31 14:22+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: ../lib/Lire/UI.pm:130 msgid "" "\n" " Welcome to Lire, the versatile log-analyser!\n" "\n" " This is a quick graphical user-interface for configuring Lire and for\n" " managing DLF stores (the directories where your reports and logs data is\n" " stored and handled).\n" "\n" " To access the menubar, press or . To wander between\n" " the different widgets contained in a window or a dialog, use the\n" " key. When done, press or , choose the Lire\n" " widget and choose quit. Your changes will be savely stored.\n" "\n" " The first time you use Lire, you are encouraged to have a look at and to\n" " modify the global Lire preferences to ensure they suit your needs.\n" " Go to the \"Lire->Preferences...\" menu to do so.\n" "\n" " If you want to generate periodical reports, you should create a\n" " new DLF store and then add it import jobs and report jobs.\n" " Import jobs are meant to parse and convert specified logfiles into the\n" " store database for further processing, while report jobs process the\n" " gathered data to produce and format reports. Be sure you have some\n" " lr_cron calls in your personal crontab.\n" "\n" " If you think you could gain significant storage room after a while,\n" " you can also clear old records since Lire will still be able to produce\n" " periodical reports by merging previous daily reports.\n" msgstr "" #: ../lib/Lire/UI.pm:267 #, perl-brace-format msgid "" " Lire {version} - the versatile log-analyser\n" "\n" " http://www.logreport.org/\n" "\n" " Lire is developed and maintained by the\n" " LogReport Development Team \n" "\n" "Copyright (c) 2000-2004 Stichting Logreport Foundation\n" "Some parts of Lire are also copyrighted by third-parties.\n" "Please consult the AUTHORS file in the Lire distribution\n" "for the complete list.\n" msgstr "" #: ../lib/Lire/OutputFormats/HTML.pm:37 msgid "(X)HTML" msgstr "" #: ../lib/Lire/UI/CompoundWidget.pm:49 msgid "-- This option does not have any attributes --" msgstr "" #: ../lib/Lire/UI/ListWidget.pm:228 ../lib/Lire/UI/PluginWidget.pm:38 msgid "-- empty list --" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:406 msgid "-- no date --" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:302 msgid "-- no stream --" msgstr "" #: ../lib/Lire/Config/Dictionary.pm:61 msgid "-- unidentified --" msgstr "" #: ../lib/Lire/UI/Prefs.pm:121 ../lib/Lire/UI/StoreWindow.pm:210 #: ../lib/Lire/UI/StoreWindow.pm:254 ../lib/Lire/UI.pm:103 msgid "< Cancel >" msgstr "" #: ../lib/Lire/UI/Prefs.pm:123 ../lib/Lire/UI/StoreWindow.pm:214 #: ../lib/Lire/UI/StoreWindow.pm:256 ../lib/Lire/UI.pm:105 msgid "< OK >" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:242 msgid "" "A list of directories which contain initialization scripts. These are short " "perl script that should register plugins with the Lire::PluginManager." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:4 msgid "" "A report output can be emailed to many addresses at the same time. Fill in " "this list with those. At least one address is required." msgstr "" #: ../lib/Lire/LrCommand.pm:219 msgid "A text file that will be included with the report." msgstr "" #: ../lib/Lire/Config/ChartSpec.pm:59 msgid "A title that will appear along the Y axis." msgstr "" #: ../lib/Lire/Config/ChartSpec.pm:54 msgid "A title that will appear under the X axis." msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:40 msgid "A title that will appears in the report." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:510 msgid "" "A typecode that can be error for line which resulted in " "an error, continuation for lines marked for processing " "at a later time and ignored for lines that were " "ignored. " msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:182 msgid "Abbreviate byte counts (Kb, Mb, ...)" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:186 msgid "Abbreviate numbers (Kb, Mb, ...)" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:190 msgid "Abbreviate time units (minutes, hours, ...)" msgstr "" #: ../lib/Lire/UI.pm:264 #, perl-brace-format msgid "About Lire {version}" msgstr "" #: ../lib/Lire/UI.pm:167 msgid "About Lire..." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:92 msgid "Activer l'affichage d'information de débogage" msgstr "" #: ../lib/Lire/UI/ListWidget.pm:114 ../lib/Lire/UI/ListWidget.pm:139 msgid "Add" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:2 msgid "Adresse de courriel où envoyer le rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:152 msgid "Adresse de courriel à partir de laquelle envoyer le rapport." msgstr "" #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:428 msgid "Afficher le nombre en Y au-dessus des barres?" msgstr "" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:362 config-spec.pot.pl:426 msgid "Afficher les nombres" msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:364 msgid "Afficher les nombres en Y à côté des points?" msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:406 msgid "Aires" msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:158 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:236 #, perl-brace-format msgid "An error occured while generating the chart: {error}" msgstr "" #: ../lib/Lire/Error.pm:53 #, perl-brace-format msgid "An error occured: {error}" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:276 msgid "An identifier for this output job." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:522 msgid "An optional message logged by the converter." msgstr "" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:75 #, perl-brace-format msgid "Analyser to use for {schema} schema" msgstr "" #: ../lib/Lire/ReportSection.pm:208 msgid "Applied filter in this section: " msgid_plural "Filters applied in this section:" msgstr[0] "" msgstr[1] "" #: ../lib/Lire/UI/ScalarListWidget.pm:43 ../lib/Lire/UI/ScalarListWidget.pm:72 msgid "Apply" msgstr "" #: ../lib/Lire/LrCommand.pm:419 msgid "Available DLF converters:" msgstr "" #: ../lib/Lire/LrCommand.pm:432 msgid "Available output formats:" msgstr "" #: ../lib/Lire/LrCommand.pm:408 msgid "Available report templates:" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:222 msgid "" "Avec \"W\", les semaines sont numérotées de 00 à 53 en prenant comme point " "de départ le premier lundi de la semaine 01. Avec \"U\", les semaines sont " "numérotées de la même façon en tenant compte du dimanche comme premier jour " "de la semaine; tandis qu'avec \"ISO\", les semaines sont calculées selon le " "standard ISO 8601:1988, de 01 à 53, avec comme semaine 01 celle qui contient " "au moins 4 jours dans l'année courante en prenant lundi comme premier jour." msgstr "" #: ../lib/Lire/LrCommand.pm:231 msgid "Backward compatibility." msgstr "" #: ../lib/Lire/UI/FileWidget.pm:38 msgid "Browse" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:128 msgid "Canal de sortie des erreurs (terminal ou redirection vers un fichier)" msgstr "" #: ../lib/Lire/LrCommand.pm:81 #, perl-brace-format msgid "Cannot create directory {directory}." msgstr "" #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:450 msgid "Caution:" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:162 msgid "" "Ce fichier en texte simple est ajouté aux courriels renvoyés par le " "répondeur automatique." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:146 msgid "" "Ce fichier est ajouté aux courriels renvoyés par le répondeur automatique." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:150 msgid "" "Ce fichier sera placé au début des courriels renvoyés par le répondeur " "automatique." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:46 msgid "" "Ce paramètre indique le service par lequel le fichier journal spécifié a été " "produit. Ce paramètre est obligatoire puisque Lire ne peut le déduire " "autrement." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:8 msgid "" "Ce paramètre pour permet d'indiquer le sujet qui apparaîtra dans les " "courriels générés automatiquement afin d'identifier les rapports reçus." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:16 msgid "" "Ceci est un gabarit de nom de fichier pouvant contenir une interpolation " "fournie par strftime(3)." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:34 msgid "" "Ceci représente le chemin d'accès au fichier journal qui doit être importé. " "Ce chemin d'accès peut correspondre à un gabarit formatté selon la " "spécification de strftime(3). Par exemple, /var/log/apache/corp.com" "%Y%m%d.log.gz sera remplacé par quelque chose semblable à " "/var/log/apache/corp.com20040124.log.gz." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:26 msgid "" "Certains fichiers de journaux requiert un traitement préalable avant de " "passer au travers du moteur principale de Lire. La commande zcat est un filtre typique utilisé pour décompresser les fichiers " "compressés par gzip ou compress à la " "volée." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:342 msgid "" "Certains fichiers de journaux, en particulier ceux produits par les " "programmes écrits par le professeur D. J. Bernstein, utilisent un format " "d'horodatage appelé \"tai64n\" qui représente les points dans le temps avec " "une précision à la nanoseconde selon la base de temps TAI. Ce programme est " "requis pour faire la conversion des secondes TAI en secondes UTC. Pour de " "plus amples informations, consultez le site web de DJB. La spécification du chemin au " "complet est facultative mais recommandée. Si vous ne traitez aucun fichier " "de journal en ce format (comme qmail ou djbdns), cette option n'est pas " "tenue en compte." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:138 msgid "" "Certains format de rapport (HTML, PDF, ...) supportent l'inclusion d'images. " "Il est alors possible d'associer un logo à ces rapports, comme par exemple " "le logo de Lire adjoint par défaut ou encore celui de votre entreprise. Ce " "paramètre peut représenter un fichier sur votre système de fichier local ou " "bien une URL." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:142 msgid "" "Certains formats de rapport supportent la gestion des hyperliens (HTML, " "PDF, ...). Dans ce cas, il est possible d'en associer un au logo d'en-tête. " "Par défaut, ce lien pointe vers le site web de la fondation LogReport. Si " "vous ne désirez lui associer aucun hyperlien, laissez ce champ vide." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:304 msgid "" "Cet identifiant peut être utilisé comme référence à la configuration de ce " "rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:338 msgid "" "Cette liste de configuration contient la configuration pour chaque stream " "DLF du store." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:118 msgid "" "Cette option peut être utilisée pour inclure du code LaTeX qui sera inséré " "dans les rapports formattés (qui incluent ceux aux formats DVI, PS et PDF). " "Ceci permet de personnaliser les en-têtes et les fontes." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:12 msgid "" "Cette option vous permet de configurer les différents attributs (un seul est " "disponible pour l'instant) du fichier généré." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:42 msgid "" "Chaque Import Job peut avoir sa propre période d'importation. Les jobs cron " "mensuels et annuels sont exécutés le premier jour du mois ou de l'année " "tandis que les hebdomadaires le sont le lundi matin à minuit." msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:169 msgid "Chart" msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:164 msgid "Charts" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:346 msgid "Chemin d'accès au fichier \"unicode.tex\"" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:170 msgid "Chemin d'accès au répertoire contenant les anciens convertisseurs DLF." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:168 msgid "Chemin d'accès à l'ancien fichier address.cf." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:288 msgid "" "Choisissez la configuration de rapport à utiliser pour cette planification." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:416 msgid "Choisissez la deuxième variable à empiler." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:424 msgid "Choisissez la quatrième variable à empiler." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:420 msgid "Choisissez la troisième variable à empiler." msgstr "" #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:432 msgid "Choisissez la variable qui représente la hauteur de la première barre." msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:400 msgid "Choisissez la variable qui représentera les composants en X des points." msgstr "" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:372 config-spec.pot.pl:404 msgid "" "Choisissez la variable qui sera représentée par la composante Y des points." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:412 msgid "Choisissez la variable représentée par le premier élément de la pile." msgstr "" #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:436 msgid "" "Choisissez optionnellement une variable qui représente la hauteur de la " "seconde barre." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:376 msgid "Choisissez une deuxième variable à tracer." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:384 msgid "Choisissez une quatrième variable à tracer." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:380 msgid "Choisissez une troisième variable à tracer." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:120 msgid "Choix de la facilité \"syslog\" à utiliser" msgstr "" #: ../lib/Lire/UI.pm:333 msgid "Choose a Store..." msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:193 #, perl-brace-format msgid "Cleaning stream '{stream}'" msgstr "" #: ../lib/Lire/UI.pm:193 msgid "Close" msgstr "" #: ../lib/Lire/LrCommand.pm:188 msgid "Common options" msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:398 msgid "Composant des X" msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:402 msgid "Composant des Y" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:298 msgid "Configuration de rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:286 msgid "Configuration de rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:336 msgid "Configuration des streams DLF" msgstr "" #: ../lib/Lire/Config/DlfStreamSpec.pm:63 #, perl-brace-format msgid "Configuration for the {schema} DlfStream" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:294 msgid "Configurations de rapport" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:241 #, perl-brace-format msgid "Configuring stream '{stream}'" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:318 msgid "Contenu de la section" msgstr "" #: ../script/lr_log2report.in:19 msgid "" "Converts using and generate a report in " "." msgstr "" #: ../script/lr_log2mail.in:24 msgid "" "Converts a log file using and email it to the recipients " "specified. The log file is read from STDIN unless the --log-file option is " "used." msgstr "" #: ../lib/Lire/UI/ListWidget.pm:115 ../lib/Lire/UI/ListWidget.pm:141 msgid "Copy" msgstr "" #: ../lib/Lire/UI.pm:302 msgid "Create a New Store..." msgstr "" #: ../lib/Lire/LrCommand.pm:83 #, perl-brace-format msgid "Created {directory}." msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:146 msgid "Custom Title" msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:492 msgid "DLF Schema for ImportJob Logging" msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:452 msgid "DLF Schema for ImportJob and AnalysisJob Statistics" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:136 msgid "DLF Streams" msgstr "" #: ../lib/Lire/OutputFormats/DVI.pm:34 msgid "DVI" msgstr "" #: ../lib/Lire/OutputFormats/DVI.pm:38 msgid "DVI report with charts." msgstr "" #: ../lib/Lire/Config/DlfStreamSpec.pm:39 msgid "Days of DLF to keep" msgstr "" #: ../lib/Lire/LrCommand.pm:489 #, perl-brace-format msgid "Decompressing log file using {gzip}..." msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:47 msgid "Defines a report section." msgstr "" #: ../lib/Lire/UI/ListWidget.pm:116 ../lib/Lire/UI/ListWidget.pm:143 msgid "Delete" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:188 msgid "" "Demande l'affichage des nombres dans un format lisible. Les unités sont " "échelonnées sur une base décimale donc \"1K requêtes\" signifie \"1000 " "requêtes\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:192 msgid "" "Demande l'affichage du temps dans un format lisible, en utilisant les " "suffixes \"m\", \"h\" et \"d\"." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:408 msgid "Dessine des aires empilées à la place de barres." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:194 msgid "Directories containing DLF schemas." msgstr "" #: ../lib/Lire/ChartTypes/Dist.pm:35 msgid "Distribution chart" msgstr "" #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:354 msgid "Distribution curve" msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:476 msgid "Dlf Created" msgstr "" #: ../lib/Lire/DlfSchema.pm:148 msgid "Dlf ID" msgstr "" #: ../lib/Lire/DlfSchema.pm:156 msgid "Dlf Source" msgstr "" #: ../lib/Lire/UI/Prefs.pm:103 msgid "Docbook Paths" msgstr "" #: ../lib/Lire/UI/ListWidget.pm:118 ../lib/Lire/UI/ListWidget.pm:147 msgid "Down" msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:396 msgid "Défini si les points seront étiquettés ou non." msgstr "" #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:356 msgid "Défini sur une courbe B-spline sera tracée par dessus le diagramme." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:300 msgid "" "Défini un rapport qui peut être utilisé pendant le Report job. Un rapport " "contient une ou plusieurs sections." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:312 msgid "Défini une section d'un rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:310 msgid "Définition de la section" msgstr "" #: ../lib/Lire/LrCommand.pm:319 msgid "ERROR " msgstr "" #: ../lib/Lire/UI/CompoundListWidget.pm:29 #: ../lib/Lire/UI/CompoundListWidget.pm:38 msgid "Edit" msgstr "" #: ../lib/Lire/UI.pm:87 #, perl-brace-format msgid "Editing {component}" msgstr "" #: ../lib/Lire/LrCommand.pm:211 msgid "Email related options" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:28 msgid "Encodage utilisé dans le fichier de journal." msgstr "" #. REFERENCE: of_txt.xml #: config-spec.pot.pl:448 msgid "Encodage utilisé dans les rapports formattés." msgstr "" #: ../lib/Lire/LrCommand.pm:546 #, perl-brace-format msgid "Encountered {error_count} errors and ignored {ignored_count} lines." msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:152 msgid "Ends:" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:203 msgid "Enter the cleaning date in the form \"YYYY-MM-DD\":" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:266 msgid "Envoyer le rapport formatté par email." msgstr "" #: ../lib/Lire/UI.pm:308 #, perl-brace-format msgid "" "Error creating store:\n" " {error}" msgstr "" #: ../script/lr_spec2pot.in:158 #, perl-brace-format msgid "Error loading spec '{spec}': {error}" msgstr "" #: ../lib/Lire/UI.pm:338 #, perl-brace-format msgid "" "Error opening store:\n" " {error}" msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:488 msgid "Errors" msgstr "" #: ../lib/Lire/OutputFormats/Excel95.pm:38 msgid "Excel95 Spreadsheet" msgstr "" #: ../lib/Lire/LrCommand.pm:543 #, perl-brace-format msgid "Extracted {dlf_count} DLF records on {line_count} lines." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:282 msgid "Fichier de configuration de rapport à utiliser." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:198 msgid "File d'entrée du répondeur" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:270 msgid "File type of the generated report" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:24 msgid "Filtre à appliquer au fichier de journal." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:314 msgid "Filtres de la section" msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:116 msgid "First Section" msgstr "" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:370 config-spec.pot.pl:410 config-spec.pot.pl:430 msgid "First Y Variable" msgstr "" #: ../lib/Lire/OutputFormats/Excel95.pm:42 msgid "Format the report as a Excel95 spreadsheet." msgstr "" #: ../script/lr_xml2report.in:17 msgid "" "Formats the XML report and save it in . If " " is omitted, the XML report will be read from STDIN. If " " is omitted, it will be output on STDOUT. Additional " "reports can be merged before formatting the report by using the --template " "and --merge options." msgstr "" #: ../script/lr_xml2mail.in:20 msgid "" "Formats the XML report and sends it by email to the recipients " "specified as argument. Additional reports can be merged before formatting " "the report by using the --template and --merge options." msgstr "" #: ../lib/Lire/LrCommand.pm:757 #, perl-brace-format msgid "Formatting report as {format} and emailing it to {emails}..." msgstr "" #: ../lib/Lire/LrCommand.pm:714 #, perl-brace-format msgid "Formatting report as {format} in {file}..." msgstr "" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:382 config-spec.pot.pl:422 msgid "Fourth Y Variable" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:14 msgid "Gabarit de nom de fichier pour le ReportJob." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:112 msgid "Garder les fichiers intermédiaires" msgstr "" #: ../lib/Lire/LrCommand.pm:619 msgid "Generating XML report..." msgstr "" #. REFERENCE: of_html.xml #: config-spec.pot.pl:440 msgid "Générer ce rapport sur une page unique" msgstr "" #: ../lib/Lire/OutputFormats/HTML.pm:41 msgid "HTML Report with charts, if ploticus is available." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:254 msgid "Horaires de génération des rapports" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:220 msgid "How are week numbers computed?" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:274 msgid "Identifiant" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:302 msgid "Identifiant du rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:132 msgid "Identifiant à utiliser pour le programme \"syslog\"" msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:141 msgid "Identifier" msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:142 msgid "" "Identifier that uniquely identifies this specification among the report " "configuration. When two reports are merged, specifications with the same " "identifier are merged together." msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:147 msgid "" "If this parameter is set, its value will be used instead of the display " "title specified in the specification. This string will interpolate $name_ref " "with the parameter's value when the report is generated." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:480 msgid "Ignored Lines" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:216 msgid "" "Il est de bon aloi de restreindre les privilèges alloués aux processus au " "minimum. Lire ne requiert pas l'utilisation du compte \"root\" pour son " "fonctionnement normal. Il est donc conseillé de créer un compte UNIX dédié. " "Lire vérifie son id d'utilisateur à son démarrage et s'arrête s'il détermine " "qu'il tourne sur le compte du superutilisateur. Cette option vous permet de " "désactiver cette vérification à vos risques et périls." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:102 msgid "" "Il est maintenant possible de personnaliser la présentation de certains " "éléments des rapports HTML. La feuille de style par défaut de Lire pour le " "HTML assure une présentation adéquate mais cette option vous donne la " "possibilité d'utiliser votre propre feuille de style." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:252 msgid "" "Il est necessaire d'identifier les report jobs afin que Lire puisse les " "traiter correctement. Utilisez cette variable pour ce faire. NOTE: Cet " "identifiant ne peut contenir que des caracteres alphanumeriques, des tirets " "et des caracteres de soulignage." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:38 msgid "" "Il est nécessaire d'identifier les import jobs afin que Lire puisse les " "traiter correctement. Utilisez cette variable pour ce faire." msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:42 msgid "Import Jobs" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:22 msgid "ImportJobs configuré dans le store actuel." msgstr "" #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:451 msgid "Important:" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:184 msgid "" "Indique à Lire d'afficher les décomptes d'octets dans un format lisible. Une " "échelonnage binaire est opéré, de sorte que \"1Kb\" ait pour valeur \"1024 " "octets\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:202 msgid "Intervale de vérification de la file d'entrée du répondeur" msgstr "" #: ../lib/Lire/UI/CommandWidget.pm:10 msgid "Invalid command" msgstr "" #: ../lib/Lire/UI/DirectoryWidget.pm:10 msgid "Invalid directory" msgstr "" #: ../lib/Lire/UI/ExecutableWidget.pm:10 msgid "Invalid executable" msgstr "" #: ../lib/Lire/UI/FileWidget.pm:96 msgid "Invalid filename" msgstr "" #: ../script/lr_cron.in:27 #, perl-brace-format msgid "" "Invalid period '{period}'. Should be one of hourly, daily, weekly, monthly " "or yearly.\n" msgstr "" #. REFERENCE: schema:lire_import_stats #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:468 config-spec.pot.pl:504 msgid "Job Id" msgstr "" #. REFERENCE: schema:lire_import_stats #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:464 config-spec.pot.pl:500 msgid "Job Name" msgstr "" #: ../lib/Lire/LrCommand.pm:101 #, perl-brace-format msgid "Keeping temporary directory {tmpdir}" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:158 msgid "" "L'adresse email à laquelle les utilisateurs du répondeur doivent répondre, " "si différente de la valeur donnée à \"lr_mail_from\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:154 msgid "" "L'adresse spécifiée dans le champ \"From\" des courriels contenant le " "rapport envoyé par le répondeur." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:246 msgid "" "La commande \"ps2pdf\" est nécessaire pour générer des rapports PDF. Elle " "fait partie de la distribution de Ghostscript. Consultez le manuel de " "l'utilisateur pour les adresses de téléchargement." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:280 msgid "" "La fréquence à laquelle cette planification de rapport sera exécutée. La " "valeur de ce paramètre peut être \"hourly\", \"daily\", \"weekly\", \"monthly" "\" or \"yearly\" (\"horaire\", \"quotidien\", \"hebdomadaire\",\"mensuel\" " "ou \"annuel\", respectivement). NOTE: pour générer des rapports " "hebdomadaires, mensuels ou annuels, au moins une planification de rapport " "quotidienne devra être disponible si vous nettoyer votre store DLF. Ce, " "parce que lorsqu'il ne peut trouver les données dans la base de donnée, Lire " "génère ces rapports par un algorithme de jonction dans lequel seuls les " "rapports quotidiens sont considérés." msgstr "" #. REFERENCE: ct_pie.xml #: config-spec.pot.pl:386 msgid "La variable des valeurs" msgstr "" #. REFERENCE: ct_pie.xml #: config-spec.pot.pl:388 msgid "" "La variable numérique qui sera utilisée pour déterminer les aires du " "diagramme." msgstr "" #: ../lib/Lire/OutputFormats/LaTeX.pm:38 msgid "LaTeX" msgstr "" #: ../lib/Lire/OutputFormats/LaTeX.pm:42 msgid "LaTeX report with charts." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:119 msgid "Last Section" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:320 msgid "Le diagramme et le sous-rapport qui seront inclus dans la section." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:122 msgid "" "Le service UNIX standard syslog a plusieurs façon de catégoriser les " "messages de journal. Vous pouvez configurer le service syslog pour trier ces " "messages dans différents fichiers selon l'indicateur de facilité. Cette " "option vous permet de sélectionner la facilité que Lire utilisera. Consultez " "la page de manuel syslog.conf(5) pour plus d'information." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:134 msgid "" "Le service UNIX standard syslog permet d'indiquer un identifiant par lequel " "chaque ligne générée par Lire sera marquée. On recommande d'utiliser une " "chaîne de caractères courte et sans espace, comme par exemple \"lire\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:130 msgid "Le service UNIX syslog" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:328 msgid "Le titre de la section qui apparaîtra dans le rapport généré." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:332 msgid "Le titre qui apparaîtra dans le rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:262 msgid "Le type cible du rapport émis." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:260 msgid "" "Les OutputJobs permettent la génération de rapports sous diverses formes et " "en plusieurs formats. Plusieurs peuvent être programmés pour la même période." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:256 msgid "" "Les ReportJobs doivent portent sur une ou plusieurs périodes, chacune " "d'elles étant alors appelée \"planification de rapport\". Une planification " "de rapport vous permet de spécifier quel rapport sera formatté, sa " "configuration ainsi que sa fréquence de génération." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:284 msgid "" "Les fichiers de configuration de rapport sont des fichiers texte avec une " "syntaxe particulière décrivant le type d'informations affichées dans le " "rapport ainsi que sa présentation. Lire est fourni avec un fichier-type de " "configuration pour chaque superservice mais vous pouvez créer le vôtre " "accordé à vos besoins." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:200 msgid "" "Les modules du répondeur automatique de Lire extraient les fichiers journaux " "des courriels, traitent leur contenu et renvoient un courriel à leur " "émetteur. Lorsque le répondeur est activé, il vérifie la présence de " "courriels entrants dans ce répertoire. Consultez le manuel de l'utilisateur " "de Lire pour savoir comment configurer la distribution des courriels vers ce " "répertoire." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:56 msgid "Les requêtes doivent-elles être archivées?" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:68 msgid "" "Les répertoires contenant des initialiseurs de convertisseurs DLF (obsolète)." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:324 msgid "Les superservices couverts dans cette section." msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:390 msgid "Ligne de régression" msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:512 msgid "Line Number" msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:508 msgid "Line Type" msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:472 msgid "Lines Read" msgstr "" #: ../lib/Lire/UI/Prefs.pm:102 msgid "Lire Paths" msgstr "" #: ../lib/Lire/UI/Prefs.pm:60 msgid "Lire Preferences" msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:142 msgid "Lire Report" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:292 msgid "" "Lire assemble les données par \"superservices\", qui en gros sont des types " "de services. Cette option vous permet de sélectionner le type de données que " "ce report job devra traiter: web, base de données, email ou n'importe quel " "type affiché dans cette liste." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:272 msgid "" "Lire peut formatter ses rapports de différentes façons, du texte simple au " "PDF, plus joli et plus approprié pour l'impression." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:126 msgid "" "Lire peut générer beaucoup d'information de sortie lors de son " "fonctionnement. Si Lire fonctionne via un traitement automatisé comme le " "répondeur ou une tâche cron, il peut être plus approprié d'envoyer ces " "données dans le journal du système pour inspection ultérieure." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:264 msgid "" "Lire peut sauvegarder ses rapports formattés dans un fichier sur le disque " "ou bien l'envoyer par email à une adresse spécifiée. Cette option vous " "permet de déterminer cela." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:316 msgid "List des filtres qui seront appliqués à cette section." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:308 msgid "List des sections définies dans le rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:258 msgid "List of OutputJobs" msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:45 msgid "List of filters that will be applied to this section." msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:44 msgid "List of sections defined in the report." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:296 msgid "Liste d'objets ReportConfig utilisés par ce store." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:60 msgid "Location of the archive" msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:516 msgid "Log Line" msgstr "" #: ../lib/Lire/LrCommand.pm:484 #, perl-brace-format msgid "Log file was compressed using {algo}." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:58 msgid "" "Lorsque ce paramètre est activé, le répondeur gardera une copie de chaque " "message reçu dans le répertoire spécifié dans la paramètre " "\"lr_archive_dir\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:94 msgid "" "Lorsque cette option est active, tous les messages de niveau \"debug\" et " "\"info\" seront dirigés vers stderr ou le journal du " "système - dépendamment de la façon dont Lire est configuré et de si vous " "utilisez la commande lr_run pour invoquer les commandes " "de Lire." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:62 msgid "" "Lorsque l'option \"lr_archive\" est active, le répertoire " "où les requêtes seront archivées." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:204 msgid "" "Lorsque le répondeur est activé, il vérifie souvent la présence de courriels " "dans la file d'entrée. Vous pouvez spécifier la fréquence de vérification " "ici, en minutes." msgstr "" #: ../lib/Lire/LrCommand.pm:255 msgid "" "Merge an additional report before formatting the report. This option can be " "used multipe times." msgstr "" #: ../lib/Lire/LrCommand.pm:245 msgid "Merging options" msgstr "" #: ../lib/Lire/LrCommand.pm:672 #, perl-brace-format msgid "Merging reports '{reports}'..." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:520 msgid "Message" msgstr "" #: ../lib/Lire/Error.pm:133 #, perl-brace-format msgid "Missing '{argument}' argument.\n" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:250 msgid "Name of the ReportJob." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:340 msgid "Name of the tai64nlocal(1) program." msgstr "" #: ../lib/Lire/OutputFormats/XML.pm:38 msgid "" "Native XML format. This keeps the report in Lire Report Markup Language." msgstr "" #: ../lib/Lire/UI.pm:175 ../lib/Lire/UI.pm:195 msgid "New..." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:515 msgid "Next" msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:122 msgid "Next Page" msgstr "" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:41 msgid "No analyser" msgstr "" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:42 msgid "No analyser will be used." msgstr "" #: ../lib/Lire/LrCommand.pm:566 #, perl-brace-format msgid "" "No default report configuration template defined for DLF converter " "\"{converter}.\"." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:281 msgid "No description." msgstr "" #: ../lib/Lire/UI/Prefs.pm:198 ../lib/Lire/UI/CompoundWidget.pm:231 msgid "No help available." msgstr "" #: ../lib/Lire/LrCommand.pm:640 #, perl-brace-format msgid "No report configuration template: {template}." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:408 msgid "No subreports were generated for this section." msgstr "" #: ../lib/Lire/LrCommand.pm:579 #, perl-brace-format msgid "No such DLF converter: {converter}." msgstr "" #: ../lib/Lire/LrCommand.pm:693 #, perl-brace-format msgid "No such output format: {format}." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:36 msgid "Nom de l'ImportJob." msgstr "" #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:447 msgid "Note:" msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:478 msgid "Number of DLF records created during the job." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:490 msgid "Number of errors encountered during that job." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:482 msgid "Number of lines ignored during that ImportJob." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:486 msgid "Number of lines saved for later processing during that ImportJob." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:474 msgid "Number of log lines processed during that job." msgstr "" #. REFERENCE: lire.xml #. REFERENCE: of_html.xml #: config-spec.pot.pl:48 config-spec.pot.pl:72 config-spec.pot.pl:74 #: config-spec.pot.pl:76 config-spec.pot.pl:78 config-spec.pot.pl:80 #: config-spec.pot.pl:82 config-spec.pot.pl:84 config-spec.pot.pl:86 #: config-spec.pot.pl:88 config-spec.pot.pl:90 config-spec.pot.pl:104 #: config-spec.pot.pl:106 config-spec.pot.pl:108 config-spec.pot.pl:172 #: config-spec.pot.pl:176 config-spec.pot.pl:206 config-spec.pot.pl:208 #: config-spec.pot.pl:210 config-spec.pot.pl:218 config-spec.pot.pl:224 #: config-spec.pot.pl:230 config-spec.pot.pl:232 config-spec.pot.pl:234 #: config-spec.pot.pl:236 config-spec.pot.pl:348 config-spec.pot.pl:350 #: config-spec.pot.pl:352 config-spec.pot.pl:438 msgid "Obsolete" msgstr "" #: ../lib/Lire/LrCommand.pm:203 msgid "Only print errors." msgstr "" #: ../lib/Lire/UI.pm:177 ../lib/Lire/UI.pm:197 msgid "Open..." msgstr "" #: ../lib/Lire/UI/Prefs.pm:101 msgid "Operational Preferences" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:10 msgid "Options spécifiques au fichier de destination choisi." msgstr "" #: ../lib/Lire/LrCommand.pm:228 msgid "Output format options" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:124 msgid "Où envoyer les messages de type progress/debug/warning/error" msgstr "" #: ../lib/Lire/OutputFormats/PDF.pm:37 msgid "PDF" msgstr "" #: ../lib/Lire/OutputFormats/PDF.pm:41 msgid "PDF report with charts." msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:170 msgid "" "Parameters for a chart that should be generated from this subreport's data." msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:165 msgid "" "Parameters for the charts that should be generated from this subreport's data" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:116 msgid "Paramétrage de LaTeX" msgstr "" #: ../lib/Lire/LrCommand.pm:534 #, perl-brace-format msgid "Parsing log file using {converter} DLF Converter..." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:50 msgid "Path to Lambda" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:226 msgid "Path to odvips" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:244 msgid "Path to ps2pdf" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:18 msgid "Path to the gs(1) program." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:20 msgid "Path to the gzip(1) program." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:32 msgid "Path to the log file that will be processed." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:238 msgid "Path to the ploticus(1) program." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:334 msgid "Path to the sendmail(1) program." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:344 msgid "Path to the tar(1) program." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:114 msgid "" "Pendant ses traitements, Lire génère des fichiers intermédiaires qu'il " "efface lorsque plus nécessaires. Si vous voulez étudier ou déboguer le " "fonctionnement de Lire, il vous est possible de l'empêcher de les effacer en " "activant cette option. Les fichiers seront conservés dans le répertoire " "indiqué dans la variable d'environnement \"TMPDIR\"." msgstr "" #: ../lib/Lire/ChartTypes/Pie.pm:35 msgid "Pie chart" msgstr "" #: ../lib/Lire/OutputFormats/Text.pm:37 msgid "Plain Text" msgstr "" #: ../lib/Lire/OutputFormats/Text.pm:41 msgid "Plain Text format." msgstr "" #: ../lib/Lire/ChartTypes/VBars.pm:35 msgid "Plot one or two variables as bars." msgstr "" #: ../lib/Lire/ChartTypes/Lines.pm:35 msgid "Plot one to four variable as lines against another." msgstr "" #: ../lib/Lire/ChartTypes/Stack.pm:35 msgid "Plot one to four variable stacked one over the other." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:64 msgid "Police utilisée dans les diagrammes" msgstr "" #: ../lib/Lire/OutputFormats/PS.pm:34 msgid "PostScript" msgstr "" #: ../lib/Lire/OutputFormats/PS.pm:38 msgid "PostScript report with charts." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:228 msgid "" "Pour générer des rapports en PostScript ou en PDF, vous devez avoir \"odvips" "\", la version Omega de \"dvips\". Cette commande est fournie avec la " "distribution TeTeX depuis sa version 0.9. Consultez le manuel de " "l'utilisateur pour les informations de télécharment." msgstr "" #: ../lib/Lire/LrCommand.pm:261 ../lib/Lire/LrCommand.pm:280 msgid "Pre Lire 2.0 report configuration file." msgstr "" #: ../lib/Lire/UI.pm:169 msgid "Preferences..." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:214 msgid "Prevent Lire from being run as root" msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:509 msgid "Previous" msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:120 msgid "Previous Page" msgstr "" #: ../lib/Lire/LrCommand.pm:198 msgid "Print Lire version and exit." msgstr "" #: ../lib/Lire/LrCommand.pm:193 msgid "" "Print usage information and exit. If \"report-templates\", \"output-formats" "\" or \"dlf-converters\" is given as argument, the command will print an " "information list for that object type." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:460 msgid "Processing Time" msgstr "" #: ../lib/Lire/UI/Prefs.pm:104 msgid "Program Paths" msgstr "" #: ../lib/Lire/UI/PluginWidget.pm:122 #, perl-brace-format msgid "Properties for {plugin}" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:136 msgid "Quel logo afficher dans l'en-tête des rapports?" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:140 msgid "" "Quelle URI devrait être pointée par le logo affiché dans vos en-têtes de " "rapports." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:100 msgid "" "Quelle feuille de style CSS doit être utilisée pour vos rapports en HTML ?" msgstr "" #: ../lib/Lire/UI.pm:171 msgid "Quit" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:154 msgid "Records:" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:54 config-spec.pot.pl:96 config-spec.pot.pl:178 #: config-spec.pot.pl:196 msgid "Remplacé dans logsource." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:110 config-spec.pot.pl:164 config-spec.pot.pl:166 #: config-spec.pot.pl:174 msgid "Remplacé dans report_output." msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:54 msgid "Report Configurations" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:47 msgid "Report Jobs" msgstr "" #: ../lib/Lire/ReportParser/LaTeXWriter.pm:164 #, perl-brace-format msgid "Report for {start} -- {end}" msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:531 #, perl-brace-format msgid "Report generated on: {date}" msgstr "" #: ../lib/Lire/ReportParser/LaTeXWriter.pm:166 #, perl-brace-format msgid "Report generated {date}" msgstr "" #: ../lib/Lire/LrCommand.pm:275 msgid "Report generation options" msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:36 msgid "Report's identifier" msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:43 msgid "Report's sections" msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:39 msgid "Report's title" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:248 msgid "ReportJobs configurés dans le store actuel." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:544 #, perl-brace-format msgid "Reporting on period: {period}" msgstr "" #: ../lib/Lire/UI/Prefs.pm:99 msgid "Reports" msgstr "" #: ../lib/Lire/UI/Prefs.pm:100 msgid "Responder Preferences" msgstr "" #: ../lib/Lire/LrCommand.pm:614 msgid "Running analysers..." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:98 msgid "Répertoires contenant des spécifications de filtres." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:212 msgid "Répertoires contenant les gabarits de spécification de rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:240 msgid "Répertoires contenant les initialiseurs de plugins." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:180 msgid "Répertoires contenant les spécifications de rapports." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:484 msgid "Saved Lines" msgstr "" #: ../lib/Lire/ChartTypes/Scat.pm:35 msgid "Scatterplot of two variables with optional regression line." msgstr "" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:374 config-spec.pot.pl:414 config-spec.pot.pl:434 msgid "Seconde variable en Y" msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:46 msgid "Section definition" msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:38 msgid "Section's Superservice" msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:51 msgid "Section's content" msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:44 msgid "Section's filters" msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:34 msgid "Section's title" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:306 msgid "Sections du rapport" msgstr "" #: ../lib/Lire/UI/CommandWidget.pm:14 msgid "Select a Command" msgstr "" #: ../lib/Lire/UI/DirectoryWidget.pm:18 msgid "Select a Directory" msgstr "" #: ../lib/Lire/UI/FileWidget.pm:100 msgid "Select a File" msgstr "" #: ../lib/Lire/UI/ExecutableWidget.pm:14 msgid "Select an Executable" msgstr "" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:80 #, perl-brace-format msgid "" "Select the analyser to use to create {schema} DLF records. If you select " "'none', no records will be created. Otherwise, the selected analyser will be " "run after each ImportJob that created records in the Dlf stream used by the " "analyser." msgstr "" #: ../lib/Lire/LrCommand.pm:236 msgid "Select the output format. Default to \"txt\"" msgstr "" #: ../lib/Lire/LrCommand.pm:285 msgid "" "Select the report configuration template that should be used for generating " "the report." msgstr "" #: ../lib/Lire/LrCommand.pm:249 msgid "" "Select the report configuration template that should be used for merging the " "reports. This option is required if you use the --merge option." msgstr "" #: ../lib/Lire/LrCommand.pm:266 msgid "" "Selects the superservice for which the report configuration file is made." msgstr "" #: ../lib/Lire/LrCommand.pm:214 msgid "Sets the email's subject." msgstr "" #: ../script/lr_log2mail.in:22 msgid "Sets the log file to convert instead of reading it from STDIN." msgstr "" #. REFERENCE: of_html.xml #: config-spec.pot.pl:442 msgid "" "Si vous désirez voir apparaître votre rapport sur une seule page, activez " "cette option. Autrement un document à plusieurs pages sera généré." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:368 msgid "" "Si vous indiquez une variable numérique, elle sera utilisée pour l'axe des X " "à la place de la variable \"case_var\"." msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:392 msgid "Spécifie si une ligne de régression sera dessinée ou non." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:456 msgid "Start Time" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:150 msgid "Starts:" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:268 msgid "Store the formatted output into a file." msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:75 msgid "Store: " msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:6 msgid "Sujet du courriel contenant le rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:322 msgid "Superservice de la section" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:290 msgid "Sélectionner le superservice pour ce rapport." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:114 #: ../lib/Lire/ReportParser/HTMLWriter.pm:426 #: ../lib/Lire/ReportParser/HTMLWriter.pm:431 #: ../lib/Lire/ReportParser/HTMLWriter.pm:503 msgid "Table Of Contents" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:144 config-spec.pot.pl:160 msgid "Texte d'avis de non-responsabilité du répondeur automatique" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:148 msgid "Texte d'explication du répondeur automatique" msgstr "" #: ../lib/Lire/LrCommand.pm:654 msgid "The -U option is required with --report-cfg" msgstr "" #: ../lib/Lire/Config/ChartSpec.pm:35 msgid "" "The basename of the chart. An extension will be appended based on the " "chart's format. If this attribute isn't set, the Subreport'id will be used." msgstr "" #: ../lib/Lire/Config/ChartSpec.pm:49 msgid "" "The categorical variable that will be used to select the case that will make " "the chart's data." msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:52 msgid "The chart and subreport that will be included in this section." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:518 msgid "The content of the log line." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:462 msgid "The duration of the job." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:506 msgid "" "The job id in which that line was processed. This is the job name plus the " "timestamp of the start of the job. " msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:470 msgid "" "The job id to which the stats relate to. This is the job name plus the " "timestamp of the start of the job. The job id makes it possible to " "distinguish between different run of the same scheduled import or analysis " "job. " msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:514 msgid "The log line number." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:502 msgid "The name of the ImportJob to which that log line is related." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:466 msgid "The name of the job." msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:35 msgid "The section's title that will appear in the generated report." msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:39 msgid "The superservices that is used by this section." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:498 msgid "The time at which that log line was processed." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:458 msgid "The time at which the job was started." msgstr "" #: ../lib/Lire/Config/ChartSpec.pm:40 msgid "The title that will appear on the chart." msgstr "" #: ../lib/Lire/Config/ChartSpec.pm:44 msgid "The type of charts to generate. Chart types are plugins." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:310 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:280 msgid "There is no entries in this table." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:454 msgid "This Dlf schema is used to store ImportJob and AnalysisJob statistics." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:494 msgid "" "This Dlf schema is used to store information related to importation and " "analysis jobs. It is this Dlf stream that will contains the lines that were " "marked for continuation, that were ignored or that had errors during an " "importation process. " msgstr "" #: ../lib/Lire/LrCommand.pm:742 msgid "This command requires the MIME::Tools CPAN module." msgstr "" #: ../lib/Lire/Config/DlfStreamSpec.pm:68 msgid "" "This configures the analysers that should be run on this DlfStream as well " "as the number of days of data to keep." msgstr "" #: ../lib/Lire/DlfSchema.pm:158 msgid "" "This field contains an identifier relating the record to the process\n" "that created it.\n" msgstr "" #: ../lib/Lire/DlfSchema.pm:150 msgid "" "This field contains an integer which uniquely identify this DLF record\n" "in the stream.\n" msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:37 msgid "This identifier can be used to refer to this report configuration." msgstr "" #: ../lib/Lire/LrCommand.pm:396 msgid "This option is obsolete." msgstr "" #: ../lib/Lire/LrCommand.pm:700 msgid "This output format has missing requirements:" msgstr "" #: ../lib/Lire/Config/DlfStreamSpec.pm:41 msgid "" "This parameter states how many days of DLF records you want to keep in the " "DlfStore. Records older than this number of days will be deleted. Use 0 to " "never expires records." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:363 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:214 #, perl-brace-format msgid "This report is missing: {reason}" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:70 msgid "This variable is superseded by plugins_init_path." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:496 msgid "Timestamp" msgstr "" #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:449 msgid "Tip:" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:326 msgid "Titre de la section" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:330 msgid "Titre du rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:52 msgid "" "To generate DVI, PostScript or PDF reports you need Lambda which is the " "Omega version of LaTeX. It is bundled with the TeTeX distribution since " "version 0.9. See the User Manual for download locations." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:221 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:334 #, perl-brace-format msgid "Total for {nrecords} records" msgstr "" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:378 config-spec.pot.pl:418 msgid "Troisième variable en Y" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:44 msgid "Type of the logfile." msgstr "" #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:360 msgid "" "Une variable numérique pour laquelle la distribution sera tracée pour les " "cas choisis pour \"case_var\"." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:542 msgid "Unknown Period" msgstr "" #: ../lib/Lire/Error.pm:154 #, perl-brace-format msgid "Unknown command: '{command}'.\n" msgstr "" #: ../lib/Lire/LrCommand.pm:387 #, perl-brace-format msgid "Unknown help section: {section}" msgstr "" #: ../lib/Lire/UI/ListWidget.pm:117 ../lib/Lire/UI/ListWidget.pm:145 msgid "Up" msgstr "" #: ../script/lr_cron.in:21 msgid "Usage: lr_cron \n" msgstr "" #: ../script/lr_report_cfg2xml.in:22 msgid "Usage: lr_report_cfg2xml \n" msgstr "" #: ../script/lr_spec2pot.in:27 msgid "" "Usage: lr_spec2pot [--cfgspecdir ]*\n" " [--reportsdir ]*\n" " [--filtersdir ]*\n" " [--pluginsdir ]*\n" " [--schemasdir ]* +\n" msgstr "" #: ../lib/Lire/LrCommand.pm:370 #, perl-brace-format msgid "Usage: {program} {usage}" msgstr "" #: ../lib/Lire/LrCommand.pm:581 msgid "Use --help dlf-converters to list available converters" msgstr "" #: ../lib/Lire/LrCommand.pm:695 msgid "Use --help output-formats to list available formats." msgstr "" #: ../lib/Lire/LrCommand.pm:642 msgid "Use --help report-templates to list available templates." msgstr "" #. REFERENCE: of_html.xml #: config-spec.pot.pl:444 msgid "Use XHTML 1.0 syntax" msgstr "" #: ../lib/Lire/LrCommand.pm:568 msgid "Use the --template option." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:30 msgid "" "Utilisez ce paramètre au cas où vos fichiers journaux sont encodés dans une " "format différent de votre système." msgstr "" #. REFERENCE: of_txt.xml #: config-spec.pot.pl:450 msgid "" "Utilisez ce paramètre au cas où vous désirez formatter vos rapports dans un " "encodage différent de celui utilisé par votre système." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:66 msgid "" "Utilisez cette option pour contrôler la fonte que Ploticus utilisera pour le " "rendu des caractères. Les fontes disponibles dépendent du format d'image " "choisi. Consultez la documentation pour plus de détails." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:156 msgid "Valeur de l'en-tête de courriel \"Reply-To\"" msgstr "" #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:358 msgid "Variable" msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:366 msgid "Variable numérique des X" msgstr "" #: ../lib/Lire/LrCommand.pm:330 msgid "WARNING " msgstr "" #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:448 msgid "Warning:" msgstr "" #. REFERENCE: of_html.xml #: config-spec.pot.pl:446 msgid "" "XHTML is the modern form of HTML. XHTML files are actually XML files with an " "HTML vocabulary. Since XHTML 1.0 is just a little bit more than HTML 4.01, " "the result displayed will not change considerably but certain people like to " "live on the bleeding edge..." msgstr "" #: ../lib/Lire/OutputFormats/XML.pm:34 msgid "XML" msgstr "" #: ../script/lr_log2mail.in:30 ../script/lr_xml2mail.in:26 msgid "You need at least one email argument." msgstr "" #: ../lib/Lire/LrCommand.pm:659 msgid "You need to use the --template option to merge reports." msgstr "" #: ../lib/Lire/LrCommand.pm:756 #, perl-brace-format msgid "Your {format} report." msgstr "" #: ../script/lr_xml2mail.in:19 msgid "[] +" msgstr "" #: ../script/lr_xml2report.in:16 msgid "[] [ []]" msgstr "" #: ../script/lr_log2mail.in:23 msgid "[] +" msgstr "" #: ../script/lr_log2report.in:18 msgid "[] [ []]" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:163 msgid "[Clean]" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:161 msgid "[Configure]" msgstr "" #: ../lib/Lire/ReportParser/LaTeXWriter.pm:330 msgid "continued on next page" msgstr "" #: ../lib/Lire/Error.pm:69 ../lib/Lire/Error.pm:78 #, perl-brace-format msgid "could not open '{file}' for reading: {error}" msgstr "" #: ../lib/Lire/Error.pm:87 #, perl-brace-format msgid "could not open '{file}' for writing: {error}" msgstr "" #: ../lib/Lire/Error.pm:141 #, perl-brace-format msgid "directory '{directory}' already exists" msgstr "" #: ../lib/Lire/LrCommand.pm:493 #, perl-brace-format msgid "error forking: {error}" msgstr "" #: ../lib/Lire/Error.pm:61 #, perl-brace-format msgid "file '{file}' is empty" msgstr "" #: ../lib/Lire/LrCommand.pm:508 #, perl-brace-format msgid "gzip exited with non zero status: {status}" msgstr "" #: ../lib/Lire/LrCommand.pm:486 msgid "gzip(1) isn't available" msgstr "" #: ../lib/Lire/Error.pm:96 #, perl-brace-format msgid "invalid option: '{option}'" msgstr "" #: ../lib/Lire/Error.pm:104 #, perl-brace-format msgid "invalid superservice: '{superservice}'" msgstr "" #: ../lib/Lire/Config/Scalar.pm:59 #, perl-brace-format msgid "invalid value for parameter '{parameter}': {value}" msgstr "" #: ../lib/Lire/Error.pm:125 #, perl-brace-format msgid "missing '{argument}' argument" msgstr "" #: ../lib/Lire/Error.pm:117 #, perl-brace-format msgid "missing '{command}' command" msgstr "" #: ../lib/Lire/OutputFormats/Excel95.pm:46 msgid "missing CPAN module Spreadsheet::WriteExcel" msgstr "" #: ../lib/Lire/Error.pm:114 #, perl-brace-format msgid "missing {make} '{command}' command" msgstr "" #: ../lib/Lire/UI/BoolWidget.pm:27 msgid "no" msgstr "" #: ../lib/Lire/LrCommand.pm:478 ../lib/Lire/LrCommand.pm:505 #, perl-brace-format msgid "read failed: {error}" msgstr "" #: ../script/lr_spec2pot.in:123 msgid "" "specs are strings of the form schema:, filter::, report:" ":, config_spec: or report_cfg:\n" msgstr "" #: ../lib/Lire/Error.pm:146 msgid "too many arguments" msgstr "" #: ../lib/Lire/UI/BoolWidget.pm:27 msgid "yes" msgstr "" #: ../lib/Lire/LrCommand.pm:349 #, perl-brace-format msgid "{program} as shipped with Lire version {version}" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:278 msgid "À quelle fréquence désirez-vous générer ce rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:40 msgid "À quelle fréquencer importer le journal dans le store" msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:394 msgid "Étiquetter les points" msgstr "" lire-2.1.1/all/po/fr.mo0000644000175000017500000010624311677606225011543 00000000000000 b.j  2p**(" + !6! K!Y!4]!!,!#!A!?"E"_"y"""$"""""##"#(1#Z#Xx##k$p$$ $ $3$ $ % %%%&9%`%z%#%% %% % %%%%% &C&c&1i&!&$& &' '8' W'+e':'(<)*)**2.*a* **<+ , , $,/,?,Q,d,Vu,,,$,-- !- .- :- D- O-Z- k-5w-'---%-_.|....H./#/ (/ 2/>/RX///-/./#+0 O0p0-v0-0.0A1.C1r1{111111K1M,23z2,2 2 22"33&35Z3 33'33#34 4,4I44 554595B5 X5d55555556!6)6?6 T6;`6666666 7 7,7A7*-8WX88I=99>9 99'9:#:+5:a:^:>R;;;n;6<=<&=c==x=/=.=&>(<>8e>">F>?2?q-@V@V@BMAA,AA B BBB|CCCCC CA DMD(E6AE4xE8EEF FFG%G7?GwG'G2G0GFH`H hHtH,H,H&H I#I*:IeI}I&I2IIJ+,J"XJ{J~JJK&K0*K[KLSU-UUUUU VVV,V3V2W)FWpW4NXXXXEX Y7#Y/[YIY YYY Z>Z YZ2cZ Z Z ZZZZZ&["+[gN[[{\\!\\0\J] O][]_]|]:]!]]']#^ =^I^ \^g^^^^^(^G^_7"_BZ_M_A_-`5`AP``7`u`RbCKc2ccc9c'4d \dhd0eef #f.f@fUfjff+g >g1Ig{gggg g ggg h8h,Oh|hh9hnhPi$dii iGi ij jj!+jgMjjj6j-k2Fk.ykk4k*k1lP@l*l ll llm$m(mYEmcmJn.Nn}n nn,nPnC3o wo#o0ooIo 2p>p&Pp wpqqqqqqrr,rIr$frrrrrrrs#sJ8ssssssst*t@t.Zt@uXu#vWvwQ7www,www-wxkxB3y"vyyy /z$:{A_{{A{.{9!|&[|+|M| |g}}6x~{~m+iX\0x! ʁҁт "#F(KMtƒadB]%45Cy<}D10L:}O   0>2o)B̉8,e'9Ɗ%3E,yċhy%}k8a} GL v!QhU091Zlc b %w+K4_MRD7yiI[O`Xz~Cu.gsA"S ?Berx>YWf\]pno(@|d;T/5#H &^-m=$tqEj',P 3J *2<6 FVN :){ Welcome to Lire, the versatile log-analyser! This is a quick graphical user-interface for configuring Lire and for managing DLF stores (the directories where your reports and logs data is stored and handled). To access the menubar, press or . To wander between the different widgets contained in a window or a dialog, use the key. When done, press or , choose the Lire widget and choose quit. Your changes will be savely stored. The first time you use Lire, you are encouraged to have a look at and to modify the global Lire preferences to ensure they suit your needs. Go to the "Lire->Preferences..." menu to do so. If you want to generate periodical reports, you should create a new DLF store and then add it import jobs and report jobs. Import jobs are meant to parse and convert specified logfiles into the store database for further processing, while report jobs process the gathered data to produce and format reports. Be sure you have some lr_cron calls in your personal crontab. If you think you could gain significant storage room after a while, you can also clear old records since Lire will still be able to produce periodical reports by merging previous daily reports. Lire {version} - the versatile log-analyser http://www.logreport.org/ Lire is developed and maintained by the LogReport Development Team Copyright (c) 2000-2004 Stichting Logreport Foundation Some parts of Lire are also copyrighted by third-parties. Please consult the AUTHORS file in the Lire distribution for the complete list. (X)HTML-- This option does not have any attributes ---- empty list ---- no date ---- no stream ---- unidentified --< Cancel >< OK >A report output can be emailed to many addresses at the same time. Fill in this list with those. At least one address is required.A text file that will be included with the report.A title that will appear along the Y axis.A title that will appear under the X axis.A title that will appears in the report.A typecode that can be error for line which resulted in an error, continuation for lines marked for processing at a later time and ignored for lines that were ignored. Abbreviate time units (minutes, hours, ...)About Lire {version}About Lire...AddAn error occured while generating the chart: {error}An error occured: {error}An optional message logged by the converter.Analyser to use for {schema} schemaApplied filter in this section: Filters applied in this section:ApplyAvailable DLF converters:Available output formats:Available report templates:Backward compatibility.BrowseCannot create directory {directory}.Caution:ChartChartsChoose a Store...Cleaning stream '{stream}'CloseCommon optionsConfiguration for the {schema} DlfStreamConfiguring stream '{stream}'Converts using and generate a report in .Converts a log file using and email it to the recipients specified. The log file is read from STDIN unless the --log-file option is used.CopyCreate a New Store...Created {directory}.Custom TitleDLF Schema for ImportJob LoggingDLF Schema for ImportJob and AnalysisJob StatisticsDLF StreamsDVIDVI report with charts.Days of DLF to keepDecompressing log file using {gzip}...Defines a report section.DeleteDirectories containing DLF schemas.Distribution chartDlf CreatedDlf IDDlf SourceDocbook PathsDownERROR EditEditing {component}Email related optionsEncountered {error_count} errors and ignored {ignored_count} lines.Ends:Enter the cleaning date in the form "YYYY-MM-DD":Error creating store: {error}Error loading spec '{spec}': {error}Error opening store: {error}ErrorsExcel95 SpreadsheetExtracted {dlf_count} DLF records on {line_count} lines.First SectionFormat the report as a Excel95 spreadsheet.Formats the XML report and save it in . If is omitted, the XML report will be read from STDIN. If is omitted, it will be output on STDOUT. Additional reports can be merged before formatting the report by using the --template and --merge options.Formats the XML report and sends it by email to the recipients specified as argument. Additional reports can be merged before formatting the report by using the --template and --merge options.Formatting report as {format} and emailing it to {emails}...Formatting report as {format} in {file}...Fourth Y VariableGenerating XML report...HTML Report with charts, if ploticus is available.How are week numbers computed?IdentifierIdentifier that uniquely identifies this specification among the report configuration. When two reports are merged, specifications with the same identifier are merged together.If this parameter is set, its value will be used instead of the display title specified in the specification. This string will interpolate $name_ref with the parameter's value when the report is generated.Ignored LinesImport JobsImportant:Invalid commandInvalid directoryInvalid executableInvalid filenameInvalid period '{period}'. Should be one of hourly, daily, weekly, monthly or yearly. Job IdJob NameKeeping temporary directory {tmpdir}LaTeXLaTeX report with charts.Last SectionLine NumberLine TypeLines ReadLire PathsLire PreferencesLire ReportList of filters that will be applied to this section.List of sections defined in the report.Location of the archiveLog LineLog file was compressed using {algo}.Merge an additional report before formatting the report. This option can be used multipe times.Merging optionsMerging reports '{reports}'...MessageMissing '{argument}' argument. Native XML format. This keeps the report in Lire Report Markup Language.New...NextNext PageNo analyserNo analyser will be used.No default report configuration template defined for DLF converter "{converter}.".No description.No help available.No report configuration template: {template}.No subreports were generated for this section.No such DLF converter: {converter}.No such output format: {format}.Note:Number of DLF records created during the job.Number of errors encountered during that job.Number of lines ignored during that ImportJob.Number of lines saved for later processing during that ImportJob.Number of log lines processed during that job.ObsoleteOnly print errors.Open...Operational PreferencesOutput format optionsPDFPDF report with charts.Parameters for a chart that should be generated from this subreport's data.Parameters for the charts that should be generated from this subreport's dataParsing log file using {converter} DLF Converter...Path to the log file that will be processed.Pie chartPlain TextPlain Text format.Plot one or two variables as bars.Plot one to four variable as lines against another.Plot one to four variable stacked one over the other.PostScriptPostScript report with charts.Pre Lire 2.0 report configuration file.Preferences...Prevent Lire from being run as rootPreviousPrevious PagePrint Lire version and exit.Print usage information and exit. If "report-templates", "output-formats" or "dlf-converters" is given as argument, the command will print an information list for that object type.Processing TimeProgram PathsProperties for {plugin}QuitRecords:Report ConfigurationsReport JobsReport for {start} -- {end}Report generated on: {date}Report generated {date}Report generation optionsReport's identifierReport's sectionsReport's titleReporting on period: {period}ReportsResponder PreferencesRunning analysers...Saved LinesScatterplot of two variables with optional regression line.Section definitionSection's SuperserviceSection's contentSection's filtersSection's titleSelect a CommandSelect a DirectorySelect a FileSelect an ExecutableSelect the analyser to use to create {schema} DLF records. If you select 'none', no records will be created. Otherwise, the selected analyser will be run after each ImportJob that created records in the Dlf stream used by the analyser.Select the output format. Default to "txt"Select the report configuration template that should be used for generating the report.Select the report configuration template that should be used for merging the reports. This option is required if you use the --merge option.Selects the superservice for which the report configuration file is made.Sets the email's subject.Sets the log file to convert instead of reading it from STDIN.Start TimeStarts:Store the formatted output into a file.Store: Table Of ContentsThe -U option is required with --report-cfgThe basename of the chart. An extension will be appended based on the chart's format. If this attribute isn't set, the Subreport'id will be used.The categorical variable that will be used to select the case that will make the chart's data.The chart and subreport that will be included in this section.The content of the log line.The duration of the job.The job id in which that line was processed. This is the job name plus the timestamp of the start of the job. The job id to which the stats relate to. This is the job name plus the timestamp of the start of the job. The job id makes it possible to distinguish between different run of the same scheduled import or analysis job. The log line number.The name of the ImportJob to which that log line is related.The name of the job.The section's title that will appear in the generated report.The superservices that is used by this section.The time at which that log line was processed.The time at which the job was started.The title that will appear on the chart.The type of charts to generate. Chart types are plugins.There is no entries in this table.This Dlf schema is used to store ImportJob and AnalysisJob statistics.This Dlf schema is used to store information related to importation and analysis jobs. It is this Dlf stream that will contains the lines that were marked for continuation, that were ignored or that had errors during an importation process. This command requires the MIME::Tools CPAN module.This configures the analysers that should be run on this DlfStream as well as the number of days of data to keep.This field contains an identifier relating the record to the process that created it. This field contains an integer which uniquely identify this DLF record in the stream. This identifier can be used to refer to this report configuration.This option is obsolete.This output format has missing requirements:This parameter states how many days of DLF records you want to keep in the DlfStore. Records older than this number of days will be deleted. Use 0 to never expires records.This report is missing: {reason}TimestampTip:To generate DVI, PostScript or PDF reports you need Lambda which is the Omega version of LaTeX. It is bundled with the TeTeX distribution since version 0.9. See the User Manual for download locations.Total for {nrecords} recordsUnknown PeriodUnknown command: '{command}'. Unknown help section: {section}UpUsage: lr_cron Usage: lr_report_cfg2xml Usage: lr_spec2pot [--cfgspecdir ]* [--reportsdir ]* [--filtersdir ]* [--pluginsdir ]* [--schemasdir ]* + Usage: {program} {usage}Use --help dlf-converters to list available convertersUse --help output-formats to list available formats.Use --help report-templates to list available templates.Use the --template option.WARNING Warning:XHTML is the modern form of HTML. XHTML files are actually XML files with an HTML vocabulary. Since XHTML 1.0 is just a little bit more than HTML 4.01, the result displayed will not change considerably but certain people like to live on the bleeding edge...XMLYou need at least one email argument.You need to use the --template option to merge reports.Your {format} report.[] +[] [ []][] +[] [ []][Clean][Configure]continued on next pagecould not open '{file}' for reading: {error}could not open '{file}' for writing: {error}directory '{directory}' already existserror forking: {error}file '{file}' is emptygzip exited with non zero status: {status}gzip(1) isn't availableinvalid option: '{option}'invalid superservice: '{superservice}'invalid value for parameter '{parameter}': {value}missing '{argument}' argumentmissing '{command}' commandmissing CPAN module Spreadsheet::WriteExcelmissing {make} '{command}' commandnoread failed: {error}specs are strings of the form schema:, filter::, report::, config_spec: or report_cfg: too many argumentsyes{program} as shipped with Lire version {version}Project-Id-Version: Lire 1.5 Report-Msgid-Bugs-To: bugs@logreport.org POT-Creation-Date: 2011-12-31 14:22+0100 PO-Revision-Date: 2004-01-20 15:47-0500 Last-Translator: Wolfgang Sourdeau Language-Team: LogReport Language: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n > 1; Bienvenue dans Lire, l'analyseur de journaux versatile! Voici une interface graphique pour vous aider à configurer Lire et vos DLF stores (les répertoires où vos données de rapport et de journaux sont archivés et gérés). Pour accéder à la barre de menu, utilisez ou . Pour naviguer entre les différents éléments graphiques d'une fenêtre, utilisez la touche . Quand vous aurez effectués toutes vos manipulations, retournez au menu avec ou , sélectionnez le menu "Lire->Quitter". Vos changements seront alors sauvegardés automatiquement. La première fois que vous utilisez Lire, il est suggéré de jeter un coup d'oeil aux paramètres de configuration de Lire pour vous assurer qu'ils correspondent bien à votre environnement et à vos besoins. Pour ce faire, allez dans le menu "Lire->Préférences...". Si vous désirez générez des rapports périodiques, vous devrez créer un nouveau DLF store et lui ajouter les "import jobs" et "report jobs" nécessaires. Les "import jobs" ont pour fonction l'analyse et la conversion des fichiers journaux dans la base de données du store pour traitement ultérieur alors que les "reports jobs" utilisent les données extraites pour produire et formatter les rapports. Assurez-vous aussi d'avoir les invocations nécessaire de lr_cron dans votre crontab. Si vous jugez pouvoir récupérer de l'espace disque de façon significative après quelques temps d'utilisation, il vous est possible de nettoyer la base de données de ses anciennes entrées. Lire pourra encore générer des rapports périodiques d'anciennes données par la jonction d'anciens rapports journaliers (pourvu que vous en ayiez configuré). Lire {version} - l'analyseur de journaux versatile http://www.logreport.org/ Lire est développé et maintainu par l'équipe de développement de LogReport Copyright (c) 2000-2004 Fondation LogReport Certaines parties de Lire sont aussi sous le copyright de parties tierces. Veuillez consulter le fichier AUTHORS de la distribution de Lire pour en savoir la liste complète. (X)HTML-- Cette option ne comporte aucun attribut ---- liste vide ---- pas de date ---- aucun stream ---- non-identifié --< Annuler >< OK >Un rapport peut être envoyé à différentes adresses de courriel en même temps. Indiquez-les dans cette liste. Au moins une adresse est requise.Un fichier texte qui sera inclus au rapport.Le titre qui apparaîtra pour l'axe des ordonnées.Le titre qui apparaîtra pour l'axe des abscisses.Le titre qui apparaîtra dans le rapport.Un code pris entre error pour les lignes erronées, continuation pour les lignes marquées pour traitement à compléter et ignored pour les lignes ignorées.Abréger les unités de temps (minutes, heures, ...)À propos de Lire {version}À propos de Lire...AjouterUne erreur est survenue lors de la génération du diagramme: {error}Une erreur est survenue: {error}Un message facultatif journalisé par le convertisseur.Analyseur à utiliser pour le schema "{schema}"Filtre appliqué à cette section: Filtres appliqués à cette section: AppliquerConvertisseurs DLF disponibles:Formats de sortie de rapport:Gabarits de rapport disponibles:Compatibilité ascendante.ParcourirImpossible de créer le répertoire "{directory}".Attention:DiagrammeDiagrammesChoisissez un store...Nettoyage du stream "{stream}"FermerOptions communesConfiguration du stream DLF "{schema}"Configuration du stream "{stream}"Converti "fichier journal" à l'aide de "convertisseur dlf" et génère un rapport dans "rapport final"Converti un fichier journal à l'aide de "convertisseur dlf" et l'envoie aux destinataires spécifiés. Le fichier journal est lu de l'entrée standard sauf si l'option "--log-file" est utilisée.CopierCréer un nouveau store...Répertoire "{directory}" créé.Titre personnaliséSchema DLF pour la journalisation des ImportJobsSchema DLF pour les statistiques liées aux ImportJobs et aux AnalysisJobsStreams DLFDVIRapport DVI avec diagrammes.Jours de DLF à conserverDécompression du fichier journal à l'aide de "{gzip}"...Défini une section d'un rapport.EffacerRépertoires contenant les schemas DLF.Diagramme de distributionDlf créésIdentifiant du DLFSource DLFChemins d'accès DocBookBasERREUR ÉditerÉdition de {component}Options liées au courrier électronique{error_count} erreurs rencontrées et {ignored_count} lignes ignorées.Fin:Entrez la date de nettoyage sous la forme "YYYY-MM-DD":Une erreur est survenue lors de la création du store: {error}Une erreur est survenue à l'ouverture de la spécification '{spec}': {error}Une erreur est survenue lors de l'ouverture du store: {error}ErreursFeuille de calcul Excel 95{dlf_count} enregistrements DLF extraits sur {line_count} lignes.Première sectionFormatte le rapport dans une feuille de calcul Excel 95Formatte le rapport xml "fichier de rapport" et le sauve dans "rapport final". Si "fichier de rapport" est omis, le rapport XML sera lu de l'entrée standard. Si "rapport final" est omis, le rapport formatté sera émis sur la sortie standard. Des rapports additionnels peuvent être joints avant le formattage du rapport en utilisant les options "--template" et "--merge".Formatte le rapport XML "fichier de rapport" et l'envoi par courrier électronique aux destinataires mis en arguments. Des rapports additionnels peuvent être joints avant le formattage du rapport en utilisant les options "--template" et "--merge".Formattage et envoi du rapport en {format} aux adresses {emails}...Formattage du rapport en {format} dans "{file}"...Quatrième variable en YGénération du rapport XML...Rapport HTML avec diagrammes, si ploticus est disponible.Calcul de la numérotation des semainesIdentifiantSymbole qui identifie cette spécification de façon unique à l'intérieur de la configuration du rapport. Lorsque deux rapports sont réunis, les spécifications au même nom sont fondues ensemble.Quand ce paramètre est spécifié, sa valeur est utilisée au lieu du titre indiqué dans la spécification. Cette chaîne remplace "$name_ref" par la valeur du paramètre lorsque le rapport est généré.Lignes ignoréesJobs d'importationImportant:Commande invalideRépertoire invalideExécutable invalideNom de fichier invalidePériode "{period}" invalide. Devrait être "hourly", "daily", "weekly", "monthly" ou "yearly" respectivement pour horaire, quotidien, hebdomadaire, mensuel et annuel. Identifiant du JobNom du JobConservation du répertoire temporaire "{tmpdir}"LaTeXRapport LaTeX avec diagrammes.Dernière sectionNuméro de ligneType de ligneLignes luesChemins d'accès LirePréférences de LireRapport LireList des filtres qui seront appliqués à cette section.List des sections définies dans le rapport.Localisation de l'archiveLigne de journalLe fichier journal était compressé à l'aide de {algo}.Joint un rapport additionnel avant le formattage du rapport. Cette option peut être indiquée plusieurs fois.Options de jonctionJonction des rapports "{reports}"...MessageArgument '{argument}' manquant. Format XML natif. Conserve les rapports en Lire Report Markup Language.Nouveau...SuivantPage suivanteAucun analyseurAucun analyseur ne sera utilisé.Aucun gabarit de configuration de rapport par défaut défini pour le convertisseur DLF "{converter}.".Aucune description.Aucune aide disponible.Aucun gabarit de configuration de rapport: {template}.Cette section ne contient aucun sous-rapport.Pas de convertisseur DLF de ce nom: "{converter}".Pas de format de sortie de ce nom: "{format}".Note:Nombre d'enregistrements DLF créés pendant ce job.Nombre d'erreurs survenues pendant ce job.Nombre de lignes ignorées pendant cet ImportJob.Nombre de lignes sauvegardées pour traitement ultérieur pendant cet ImportJob.Nombre de lignes traitées pendant ce job.ObsolèteAffiche seulement les erreurs.Ouvrir...Paramètres fonctionnelsOptions du format de sortiePDFRapport PDF avec diagrammes.Paramètres un diagramme qui devrait être généré par les données de ce sous-rapport.Paramètres pour les diagrammes qui devraient être générés par les données de ce sous-rapport.Analyze du fichier journal à l'aide du convertisseur DLF "{converter}"...Chemin d'accès au fichier journal à traiter.Diagramme en secteursTexte simpleFormat texte simple.Représente une ou deux variables en barres.Représente de une à quatre variables en lignes alignées l'une contre l'autre.Représente de une à quatre variables empilées l'une sur l'autre.PostScriptRapport PostScript avec diagrammes.Fichier de configuration antérieur à Lire 2.0.Préférences...Empêcher Lire d'être exécuté avec les privilèges du superutilisateurPrécédentPage précédenteAffiche la version de Lire et termine.Affiche l'information d'utilisation et se termine. Si "report-templates", "output-formats" ou "dlf-converters" sont indiqués comme arguments, la commande affichera la liste des valeurs disponibles pour les gabarits, les formats de sortie et les convertisseurs DLF.Heure de traitementChemins d'accès utilitairesPropriétés pour {plugin}QuitterEnregistrements:Configurations de rapportJobs de rapportRapport de {start} à {end}Date de génération: {date}Date de génération: {date}Options de génération des rapportsIdentifiant du rapportSections du rapportTitre du rapportPériode couverte: {period}RapportsParamètres du répondeurExécution des analyseurs...Lignes sauvegardéesNuage de points pour deux variables avec ligne de régression optionnelle.Définition de la sectionSuperservice de la sectionContenu de la sectionFiltres de la sectionTitre de la sectionChoisissez une commandeChoisissez un répertoireChoisissez un fichierChoisissez un exécutableChoisissez l'analyseur à utiliser pour créer des enregistrement DLF {schema}. Si vous sélectionnez "aucun", alors aucun enregistrement ne sera créé. Autrement, l'analyseur choisi sera exécuté après chaque ImportJob qui aura créé des enregistrement dans le stream DLF utilisé par l'analyseur.Choisissez le format de sortie. La valeur par défaut est "txt".Choisissez le gabarit de configuration de rapport à utiliser pour générer le rapport.Choisissez le gabartit de configuration de rapport à utiliser pour joindre les rapports. Cette option est obligatoire si vous utilisez l'option "--merge".Sélectionner le superservice auquel le fichier de configuration de rapport correspond.Défini le sujet des courriels.Défini le fichier journal à convertir au lieu de le lire de l'entrée standard.Heure de débutDébut:Placer la sortie formattée dans un fichier.Store: Table des matièresL'option "-U" est requise avec "--report-cfg"Le nom du diagramme. L'extension qui y sera ajoutée en fonction de son format. Si cet attribut n'est pas spécifié, l'identifiant du sous-rapport sera utilisé à la place.La variable catégorique qui sera utilisée pour déterminer les données à représenter sur le diagramme.Le diagramme et le sous-rapport qui seront inclus dans la section.Le contenu de la ligne de journal.La durée du job.L'identifiant du job pendant lequel cette ligne a été traitée. Il s'agit du nom du job ajouté de l'horodatage du début du job.L'identifiant du job à laquelle les statistiques se réfèrent. Il s'agit du nom du job ajouté du pointage du temps de démarrage du job. Cela permet de faire la distinction entre les différentes exécutions de la même planification d'ImportJob ou d'AnalysisJob.Le numéro de ligne dans le journal.Le nom de l'ImportJob auquel cette ligne de journal est relative.Le nom du job.Le titre de la section qui apparaîtra dans le rapport généré.Les superservices couverts dans cette section.Le moment auquel cette ligne de journal a été traitée.L'heure à laquelle le job a démarréLe titre qui apparaîtra dans le diagramme.Le type de diagrammes à générer. Les types de diagrammes sont des plugins.Aucune entrée dans cette table.Ce schema Dlf est utilisé pour emmagasiner les statistiques liées aux ImportJobs et aux AnalysisJobs.Ce schema DLF est utilisé pour emmagasiner les informations reliées aux jobs d'importation et d'analyse. C'est ce stream DLF qui contiendra les lignes marquées comme à compléter, ignorées ou erronées pendant le processus d'importation.Cette commande requiert le module MIME::Tools de CPAN.Ceci configure les analyseurs qui seront appliqués sur ce DlfStream ainsi que le nombre de jours de données à conserver.Ce champ contient un nombre entier indiquant la relation entre l'enregistrement au processus qui l'a créé. Ce champ contient un nombre entier qui identifie cet enregistrement DLF dans le stream de façon unique. Cet identifiant peut être utilisé comme référence à la configuration de ce rapport.Cette option est obsolète.Ce format de sortie a des pré-requis manquants:Ce paramètre indique le nombre de jours d'enregistrement DLF vous désirez conserver dans le DlfStore. Les enregistrements anciens de plus que ce nombre de jours seront effacés. Indiquez "0" pour désactiver l'expiration des enregistrements.Ce rapport est manquant: {reason}HorodatageAstuce:Pour générer des rapports en DVI, en PostScript ou en PDF, vous devez avoir Lambda, la version Omega de LaTeX. Il est fourni avec la distribution TeTeX depuis sa version 0.9. Consultez le manuel de l'utilisateur pour les informations de télécharment.Total pour {nrecords} enreg.période indéfinieCommande inconnue: '{command}'. Section d'aide inconnue: {section}HautUtilisation: lr_cron Utilisation: lr_report_cfg2xml Utilisation: lr_spec2pot [--cfgspecdir ]* [--reportsdir ]* [--filtersdir ]* [--pluginsdir ]* [--schemasdir ]* + Utilisation: {program} {usage}Utilisez l'option "--help dlf-converters" pour lister les différents convertisseurs disponibles.Utilisez l'option "--help output-formats" pour lister les différents formats de sortie disponibles.Utilisez l'option "--help report-templates" pour lister les différents gabarits disponibles.Utilisez l'option "--template".AVERTISSEMENT Avertissement:XHTML est la forme actuelle de HTML. Les fichiers XHTML sont en réalité des fichiers XML avec un vocabulaire HTML. Puisque XHTML 1.0 n'est tout au plus qu'une variante améliorée de HTML 4.01, le résultat affiché ne devrait pas varier beaucoup. Toutefois certains aiment vivre au fait des technologies...XMLAu moins une adresse de courriel est requise comme argument.Vous devez utiliser l'option "--template" pour joindre des rapports.Votre rapport en {format}.[] +[] +[] +[] [ []][Nettoyer][Configurer]poursuivi à la page suivanteimpossible d'ouvrir '{file}' en lecture: {error}impossible d'ouvrir '{file}' en écriture: {error}le répertoire '{directory}' existe déjaUne erreur est survenue lors du détachement du processur: {error}le fichier '{file}' est videgzip a terminé avec un état d'erreur non-nul: {status}gzip(1) n'est pas disponibleoption invalide: '{option}'superservice invalide: "{superservice}"valeur invalide pour le paramètre '{parameter}': {value}argument '{argument}' manquantla commande "{command}" est manquantele module CPAN Spreadsheet::WriteExcel est manquantla commande {make} "{command}" est manquantenonlecture erronée: {error}Les specs sont des chaînes de caractères ayant pour forme schema:, filter::, report::, config_spec: ou report_cfg: trop d'argumentsoui{program}, fourni avec Lire {version}lire-2.1.1/all/po/fr.po0000644000175000017500000033523711677606225011555 00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Stichting LogReport Foundation # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # # $Id: fr.po,v 1.72 2009/01/17 11:59:47 vanbaal Exp $ # msgid "" msgstr "" "Project-Id-Version: Lire 1.5\n" "Report-Msgid-Bugs-To: bugs@logreport.org\n" "POT-Creation-Date: 2011-12-31 14:22+0100\n" "PO-Revision-Date: 2004-01-20 15:47-0500\n" "Last-Translator: Wolfgang Sourdeau \n" "Language-Team: LogReport \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" #: ../lib/Lire/UI.pm:130 msgid "" "\n" " Welcome to Lire, the versatile log-analyser!\n" "\n" " This is a quick graphical user-interface for configuring Lire and for\n" " managing DLF stores (the directories where your reports and logs data is\n" " stored and handled).\n" "\n" " To access the menubar, press or . To wander between\n" " the different widgets contained in a window or a dialog, use the\n" " key. When done, press or , choose the Lire\n" " widget and choose quit. Your changes will be savely stored.\n" "\n" " The first time you use Lire, you are encouraged to have a look at and to\n" " modify the global Lire preferences to ensure they suit your needs.\n" " Go to the \"Lire->Preferences...\" menu to do so.\n" "\n" " If you want to generate periodical reports, you should create a\n" " new DLF store and then add it import jobs and report jobs.\n" " Import jobs are meant to parse and convert specified logfiles into the\n" " store database for further processing, while report jobs process the\n" " gathered data to produce and format reports. Be sure you have some\n" " lr_cron calls in your personal crontab.\n" "\n" " If you think you could gain significant storage room after a while,\n" " you can also clear old records since Lire will still be able to produce\n" " periodical reports by merging previous daily reports.\n" msgstr "" "\n" " Bienvenue dans Lire, l'analyseur de journaux versatile!\n" "\n" " Voici une interface graphique pour vous aider à configurer Lire et vos\n" " DLF stores (les répertoires où vos données de rapport et de journaux\n" " sont archivés et gérés).\n" "\n" " Pour accéder à la barre de menu, utilisez ou .\n" " Pour naviguer entre les différents éléments graphiques d'une fenêtre,\n" " utilisez la touche . Quand vous aurez effectués toutes vos\n" " manipulations, retournez au menu avec ou , sélectionnez\n" " le menu \"Lire->Quitter\". Vos changements seront alors sauvegardés\n" " automatiquement.\n" "\n" " La première fois que vous utilisez Lire, il est suggéré de jeter un\n" " coup d'oeil aux paramètres de configuration de Lire pour vous assurer\n" " qu'ils correspondent bien à votre environnement et à vos besoins.\n" " Pour ce faire, allez dans le menu \"Lire->Préférences...\".\n" "\n" " Si vous désirez générez des rapports périodiques, vous devrez créer un\n" " nouveau DLF store et lui ajouter les \"import jobs\" et \"report jobs\"\n" " nécessaires. Les \"import jobs\" ont pour fonction l'analyse et la\n" " conversion des fichiers journaux dans la base de données du store pour\n" " traitement ultérieur alors que les \"reports jobs\" utilisent les\n" " données extraites pour produire et formatter les rapports.\n" " Assurez-vous aussi d'avoir les invocations nécessaire de lr_cron dans\n" " votre crontab.\n" "\n" " Si vous jugez pouvoir récupérer de l'espace disque de façon significative\n" " après quelques temps d'utilisation, il vous est possible de nettoyer la\n" " base de données de ses anciennes entrées. Lire pourra encore générer\n" " des rapports périodiques d'anciennes données par la jonction d'anciens\n" " rapports journaliers (pourvu que vous en ayiez configuré).\n" #: ../lib/Lire/UI.pm:267 #, perl-brace-format msgid "" " Lire {version} - the versatile log-analyser\n" "\n" " http://www.logreport.org/\n" "\n" " Lire is developed and maintained by the\n" " LogReport Development Team \n" "\n" "Copyright (c) 2000-2004 Stichting Logreport Foundation\n" "Some parts of Lire are also copyrighted by third-parties.\n" "Please consult the AUTHORS file in the Lire distribution\n" "for the complete list.\n" msgstr "" " Lire {version} - l'analyseur de journaux versatile\n" "\n" " http://www.logreport.org/\n" "\n" " Lire est développé et maintainu par l'équipe \n" " de développement de LogReport \n" "\n" "Copyright (c) 2000-2004 Fondation LogReport\n" "Certaines parties de Lire sont aussi sous le copyright de\n" "parties tierces. Veuillez consulter le fichier AUTHORS de\n" "la distribution de Lire pour en savoir la liste complète.\n" #: ../lib/Lire/OutputFormats/HTML.pm:37 msgid "(X)HTML" msgstr "(X)HTML" #: ../lib/Lire/UI/CompoundWidget.pm:49 msgid "-- This option does not have any attributes --" msgstr "-- Cette option ne comporte aucun attribut --" #: ../lib/Lire/UI/ListWidget.pm:228 ../lib/Lire/UI/PluginWidget.pm:38 msgid "-- empty list --" msgstr "-- liste vide --" #: ../lib/Lire/UI/StoreWindow.pm:406 msgid "-- no date --" msgstr "-- pas de date --" #: ../lib/Lire/UI/StoreWindow.pm:302 msgid "-- no stream --" msgstr "-- aucun stream --" #: ../lib/Lire/Config/Dictionary.pm:61 msgid "-- unidentified --" msgstr "-- non-identifié --" #: ../lib/Lire/UI/Prefs.pm:121 ../lib/Lire/UI/StoreWindow.pm:210 #: ../lib/Lire/UI/StoreWindow.pm:254 ../lib/Lire/UI.pm:103 msgid "< Cancel >" msgstr "< Annuler >" #: ../lib/Lire/UI/Prefs.pm:123 ../lib/Lire/UI/StoreWindow.pm:214 #: ../lib/Lire/UI/StoreWindow.pm:256 ../lib/Lire/UI.pm:105 msgid "< OK >" msgstr "< OK >" #. REFERENCE: lire.xml #: config-spec.pot.pl:242 #, fuzzy msgid "" "A list of directories which contain initialization scripts. These are short " "perl script that should register plugins with the Lire::PluginManager." msgstr "" "Une liste de répertoires contenant des scripts d'initialisation. Il s'agit " "de petits scripts perl qui enregistrent les plugins auprès de Lire::" "PluginManager." #. REFERENCE: lire.xml #: config-spec.pot.pl:4 msgid "" "A report output can be emailed to many addresses at the same time. Fill in " "this list with those. At least one address is required." msgstr "" "Un rapport peut être envoyé à différentes adresses de courriel en même " "temps. Indiquez-les dans cette liste. Au moins une adresse est requise." #: ../lib/Lire/LrCommand.pm:219 msgid "A text file that will be included with the report." msgstr "Un fichier texte qui sera inclus au rapport." #: ../lib/Lire/Config/ChartSpec.pm:59 msgid "A title that will appear along the Y axis." msgstr "Le titre qui apparaîtra pour l'axe des ordonnées." #: ../lib/Lire/Config/ChartSpec.pm:54 msgid "A title that will appear under the X axis." msgstr "Le titre qui apparaîtra pour l'axe des abscisses." #: ../lib/Lire/Config/ReportSpec.pm:40 msgid "A title that will appears in the report." msgstr "Le titre qui apparaîtra dans le rapport." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:510 msgid "" "A typecode that can be error for line which resulted in " "an error, continuation for lines marked for processing " "at a later time and ignored for lines that were " "ignored. " msgstr "" "Un code pris entre error pour les lignes erronées, " "continuation pour les lignes marquées pour traitement à " "compléter et ignored pour les lignes ignorées." #. REFERENCE: lire.xml #: config-spec.pot.pl:182 #, fuzzy msgid "Abbreviate byte counts (Kb, Mb, ...)" msgstr "Abréger les unités de temps (minutes, heures, ...)" #. REFERENCE: lire.xml #: config-spec.pot.pl:186 #, fuzzy msgid "Abbreviate numbers (Kb, Mb, ...)" msgstr "Abréger les nombres (Ko, Mo, ...)" #. REFERENCE: lire.xml #: config-spec.pot.pl:190 msgid "Abbreviate time units (minutes, hours, ...)" msgstr "Abréger les unités de temps (minutes, heures, ...)" #: ../lib/Lire/UI.pm:264 #, perl-brace-format msgid "About Lire {version}" msgstr "À propos de Lire {version}" #: ../lib/Lire/UI.pm:167 msgid "About Lire..." msgstr "À propos de Lire..." #. REFERENCE: lire.xml #: config-spec.pot.pl:92 msgid "Activer l'affichage d'information de débogage" msgstr "" #: ../lib/Lire/UI/ListWidget.pm:114 ../lib/Lire/UI/ListWidget.pm:139 msgid "Add" msgstr "Ajouter" #. REFERENCE: lire.xml #: config-spec.pot.pl:2 msgid "Adresse de courriel où envoyer le rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:152 msgid "Adresse de courriel à partir de laquelle envoyer le rapport." msgstr "" #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:428 msgid "Afficher le nombre en Y au-dessus des barres?" msgstr "" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:362 config-spec.pot.pl:426 msgid "Afficher les nombres" msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:364 msgid "Afficher les nombres en Y à côté des points?" msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:406 msgid "Aires" msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:158 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:236 #, perl-brace-format msgid "An error occured while generating the chart: {error}" msgstr "Une erreur est survenue lors de la génération du diagramme: {error}" #: ../lib/Lire/Error.pm:53 #, perl-brace-format msgid "An error occured: {error}" msgstr "Une erreur est survenue: {error}" #. REFERENCE: lire.xml #: config-spec.pot.pl:276 #, fuzzy msgid "An identifier for this output job." msgstr "Un identifiant pour cet output job." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:522 msgid "An optional message logged by the converter." msgstr "Un message facultatif journalisé par le convertisseur." #: ../lib/Lire/Config/DlfAnalyserSpec.pm:75 #, perl-brace-format msgid "Analyser to use for {schema} schema" msgstr "Analyseur à utiliser pour le schema \"{schema}\"" #: ../lib/Lire/ReportSection.pm:208 msgid "Applied filter in this section: " msgid_plural "Filters applied in this section:" msgstr[0] "Filtre appliqué à cette section: " msgstr[1] "Filtres appliqués à cette section: " #: ../lib/Lire/UI/ScalarListWidget.pm:43 ../lib/Lire/UI/ScalarListWidget.pm:72 msgid "Apply" msgstr "Appliquer" #: ../lib/Lire/LrCommand.pm:419 msgid "Available DLF converters:" msgstr "Convertisseurs DLF disponibles:" #: ../lib/Lire/LrCommand.pm:432 msgid "Available output formats:" msgstr "Formats de sortie de rapport:" #: ../lib/Lire/LrCommand.pm:408 msgid "Available report templates:" msgstr "Gabarits de rapport disponibles:" #. REFERENCE: lire.xml #: config-spec.pot.pl:222 msgid "" "Avec \"W\", les semaines sont numérotées de 00 à 53 en prenant comme point " "de départ le premier lundi de la semaine 01. Avec \"U\", les semaines sont " "numérotées de la même façon en tenant compte du dimanche comme premier jour " "de la semaine; tandis qu'avec \"ISO\", les semaines sont calculées selon le " "standard ISO 8601:1988, de 01 à 53, avec comme semaine 01 celle qui contient " "au moins 4 jours dans l'année courante en prenant lundi comme premier jour." msgstr "" #: ../lib/Lire/LrCommand.pm:231 msgid "Backward compatibility." msgstr "Compatibilité ascendante." #: ../lib/Lire/UI/FileWidget.pm:38 msgid "Browse" msgstr "Parcourir" #. REFERENCE: lire.xml #: config-spec.pot.pl:128 #, fuzzy msgid "Canal de sortie des erreurs (terminal ou redirection vers un fichier)" msgstr "Canal de sortie des erreurs (terminal ou redirection vers un fichier)" #: ../lib/Lire/LrCommand.pm:81 #, perl-brace-format msgid "Cannot create directory {directory}." msgstr "Impossible de créer le répertoire \"{directory}\"." #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:450 msgid "Caution:" msgstr "Attention:" #. REFERENCE: lire.xml #: config-spec.pot.pl:162 msgid "" "Ce fichier en texte simple est ajouté aux courriels renvoyés par le " "répondeur automatique." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:146 msgid "" "Ce fichier est ajouté aux courriels renvoyés par le répondeur automatique." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:150 msgid "" "Ce fichier sera placé au début des courriels renvoyés par le répondeur " "automatique." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:46 msgid "" "Ce paramètre indique le service par lequel le fichier journal spécifié a été " "produit. Ce paramètre est obligatoire puisque Lire ne peut le déduire " "autrement." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:8 msgid "" "Ce paramètre pour permet d'indiquer le sujet qui apparaîtra dans les " "courriels générés automatiquement afin d'identifier les rapports reçus." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:16 msgid "" "Ceci est un gabarit de nom de fichier pouvant contenir une interpolation " "fournie par strftime(3)." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:34 #, fuzzy msgid "" "Ceci représente le chemin d'accès au fichier journal qui doit être importé. " "Ce chemin d'accès peut correspondre à un gabarit formatté selon la " "spécification de strftime(3). Par exemple, /var/log/apache/corp.com" "%Y%m%d.log.gz sera remplacé par quelque chose semblable à " "/var/log/apache/corp.com20040124.log.gz." msgstr "" "Ceci représente le chemin d'accès au fichier journal qui doit être importé. " "Ce chemin d'accès peut correspondre à un gabarit formatté selon la " "spécification de strftime(3). Par exemple, /var/log/apache/corp.com" "%Y%m%d.log.gz sera remplacé par quelque chose semblable à " "/var/log/apache/corp.com20040124.log.gz." #. REFERENCE: lire.xml #: config-spec.pot.pl:26 msgid "" "Certains fichiers de journaux requiert un traitement préalable avant de " "passer au travers du moteur principale de Lire. La commande zcat est un filtre typique utilisé pour décompresser les fichiers " "compressés par gzip ou compress à la " "volée." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:342 msgid "" "Certains fichiers de journaux, en particulier ceux produits par les " "programmes écrits par le professeur D. J. Bernstein, utilisent un format " "d'horodatage appelé \"tai64n\" qui représente les points dans le temps avec " "une précision à la nanoseconde selon la base de temps TAI. Ce programme est " "requis pour faire la conversion des secondes TAI en secondes UTC. Pour de " "plus amples informations, consultez le site web de DJB. La spécification du chemin au " "complet est facultative mais recommandée. Si vous ne traitez aucun fichier " "de journal en ce format (comme qmail ou djbdns), cette option n'est pas " "tenue en compte." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:138 msgid "" "Certains format de rapport (HTML, PDF, ...) supportent l'inclusion d'images. " "Il est alors possible d'associer un logo à ces rapports, comme par exemple " "le logo de Lire adjoint par défaut ou encore celui de votre entreprise. Ce " "paramètre peut représenter un fichier sur votre système de fichier local ou " "bien une URL." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:142 msgid "" "Certains formats de rapport supportent la gestion des hyperliens (HTML, " "PDF, ...). Dans ce cas, il est possible d'en associer un au logo d'en-tête. " "Par défaut, ce lien pointe vers le site web de la fondation LogReport. Si " "vous ne désirez lui associer aucun hyperlien, laissez ce champ vide." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:304 msgid "" "Cet identifiant peut être utilisé comme référence à la configuration de ce " "rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:338 #, fuzzy msgid "" "Cette liste de configuration contient la configuration pour chaque stream " "DLF du store." msgstr "" "Cette liste de configuration contient la configuration pour chaque stream " "DLF du store." #. REFERENCE: lire.xml #: config-spec.pot.pl:118 msgid "" "Cette option peut être utilisée pour inclure du code LaTeX qui sera inséré " "dans les rapports formattés (qui incluent ceux aux formats DVI, PS et PDF). " "Ceci permet de personnaliser les en-têtes et les fontes." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:12 msgid "" "Cette option vous permet de configurer les différents attributs (un seul est " "disponible pour l'instant) du fichier généré." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:42 msgid "" "Chaque Import Job peut avoir sa propre période d'importation. Les jobs cron " "mensuels et annuels sont exécutés le premier jour du mois ou de l'année " "tandis que les hebdomadaires le sont le lundi matin à minuit." msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:169 msgid "Chart" msgstr "Diagramme" #: ../lib/Lire/Config/XMLSpecListSpec.pm:164 msgid "Charts" msgstr "Diagrammes" #. REFERENCE: lire.xml #: config-spec.pot.pl:346 msgid "Chemin d'accès au fichier \"unicode.tex\"" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:170 msgid "Chemin d'accès au répertoire contenant les anciens convertisseurs DLF." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:168 msgid "Chemin d'accès à l'ancien fichier address.cf." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:288 msgid "" "Choisissez la configuration de rapport à utiliser pour cette planification." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:416 msgid "Choisissez la deuxième variable à empiler." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:424 msgid "Choisissez la quatrième variable à empiler." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:420 msgid "Choisissez la troisième variable à empiler." msgstr "" #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:432 msgid "Choisissez la variable qui représente la hauteur de la première barre." msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:400 #, fuzzy msgid "Choisissez la variable qui représentera les composants en X des points." msgstr "" "Choisissez la variable qui sera représentée par la composante Y des points." #. REFERENCE: ct_lines.xml #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:372 config-spec.pot.pl:404 msgid "" "Choisissez la variable qui sera représentée par la composante Y des points." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:412 msgid "Choisissez la variable représentée par le premier élément de la pile." msgstr "" #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:436 #, fuzzy msgid "" "Choisissez optionnellement une variable qui représente la hauteur de la " "seconde barre." msgstr "" "Choisissez optionnellement une variable qui représente la hauteur de la " "seconde barre." #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:376 msgid "Choisissez une deuxième variable à tracer." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:384 msgid "Choisissez une quatrième variable à tracer." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:380 msgid "Choisissez une troisième variable à tracer." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:120 msgid "Choix de la facilité \"syslog\" à utiliser" msgstr "" #: ../lib/Lire/UI.pm:333 msgid "Choose a Store..." msgstr "Choisissez un store..." #: ../lib/Lire/UI/StoreWindow.pm:193 #, perl-brace-format msgid "Cleaning stream '{stream}'" msgstr "Nettoyage du stream \"{stream}\"" #: ../lib/Lire/UI.pm:193 msgid "Close" msgstr "Fermer" #: ../lib/Lire/LrCommand.pm:188 msgid "Common options" msgstr "Options communes" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:398 msgid "Composant des X" msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:402 msgid "Composant des Y" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:298 msgid "Configuration de rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:286 msgid "Configuration de rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:336 #, fuzzy msgid "Configuration des streams DLF" msgstr "Configuration du stream \"{stream}\"" #: ../lib/Lire/Config/DlfStreamSpec.pm:63 #, perl-brace-format msgid "Configuration for the {schema} DlfStream" msgstr "Configuration du stream DLF \"{schema}\"" #. REFERENCE: lire.xml #: config-spec.pot.pl:294 #, fuzzy msgid "Configurations de rapport" msgstr "Configurations de rapport" #: ../lib/Lire/UI/StoreWindow.pm:241 #, perl-brace-format msgid "Configuring stream '{stream}'" msgstr "Configuration du stream \"{stream}\"" #. REFERENCE: lire.xml #: config-spec.pot.pl:318 msgid "Contenu de la section" msgstr "" #: ../script/lr_log2report.in:19 msgid "" "Converts using and generate a report in " "." msgstr "" "Converti \"fichier journal\" à l'aide de \"convertisseur dlf\" et génère un " "rapport dans \"rapport final\"" #: ../script/lr_log2mail.in:24 msgid "" "Converts a log file using and email it to the recipients " "specified. The log file is read from STDIN unless the --log-file option is " "used." msgstr "" "Converti un fichier journal à l'aide de \"convertisseur dlf\" et l'envoie " "aux destinataires spécifiés. Le fichier journal est lu de l'entrée standard " "sauf si l'option \"--log-file\" est utilisée." #: ../lib/Lire/UI/ListWidget.pm:115 ../lib/Lire/UI/ListWidget.pm:141 msgid "Copy" msgstr "Copier" #: ../lib/Lire/UI.pm:302 msgid "Create a New Store..." msgstr "Créer un nouveau store..." #: ../lib/Lire/LrCommand.pm:83 #, perl-brace-format msgid "Created {directory}." msgstr "Répertoire \"{directory}\" créé." #: ../lib/Lire/Config/XMLSpecListSpec.pm:146 msgid "Custom Title" msgstr "Titre personnalisé" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:492 msgid "DLF Schema for ImportJob Logging" msgstr "Schema DLF pour la journalisation des ImportJobs" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:452 msgid "DLF Schema for ImportJob and AnalysisJob Statistics" msgstr "" "Schema DLF pour les statistiques liées aux ImportJobs et aux AnalysisJobs" #: ../lib/Lire/UI/StoreWindow.pm:136 msgid "DLF Streams" msgstr "Streams DLF" #: ../lib/Lire/OutputFormats/DVI.pm:34 msgid "DVI" msgstr "DVI" #: ../lib/Lire/OutputFormats/DVI.pm:38 msgid "DVI report with charts." msgstr "Rapport DVI avec diagrammes." #: ../lib/Lire/Config/DlfStreamSpec.pm:39 msgid "Days of DLF to keep" msgstr "Jours de DLF à conserver" #: ../lib/Lire/LrCommand.pm:489 #, perl-brace-format msgid "Decompressing log file using {gzip}..." msgstr "Décompression du fichier journal à l'aide de \"{gzip}\"..." #: ../lib/Lire/Config/ReportSpec.pm:47 msgid "Defines a report section." msgstr "Défini une section d'un rapport." #: ../lib/Lire/UI/ListWidget.pm:116 ../lib/Lire/UI/ListWidget.pm:143 msgid "Delete" msgstr "Effacer" #. REFERENCE: lire.xml #: config-spec.pot.pl:188 msgid "" "Demande l'affichage des nombres dans un format lisible. Les unités sont " "échelonnées sur une base décimale donc \"1K requêtes\" signifie \"1000 " "requêtes\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:192 msgid "" "Demande l'affichage du temps dans un format lisible, en utilisant les " "suffixes \"m\", \"h\" et \"d\"." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:408 msgid "Dessine des aires empilées à la place de barres." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:194 msgid "Directories containing DLF schemas." msgstr "Répertoires contenant les schemas DLF." #: ../lib/Lire/ChartTypes/Dist.pm:35 msgid "Distribution chart" msgstr "Diagramme de distribution" #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:354 #, fuzzy msgid "Distribution curve" msgstr "Courbe de distribution" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:476 msgid "Dlf Created" msgstr "Dlf créés" #: ../lib/Lire/DlfSchema.pm:148 msgid "Dlf ID" msgstr "Identifiant du DLF" #: ../lib/Lire/DlfSchema.pm:156 msgid "Dlf Source" msgstr "Source DLF" #: ../lib/Lire/UI/Prefs.pm:103 msgid "Docbook Paths" msgstr "Chemins d'accès DocBook" #: ../lib/Lire/UI/ListWidget.pm:118 ../lib/Lire/UI/ListWidget.pm:147 msgid "Down" msgstr "Bas" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:396 msgid "Défini si les points seront étiquettés ou non." msgstr "" #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:356 msgid "Défini sur une courbe B-spline sera tracée par dessus le diagramme." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:300 #, fuzzy msgid "" "Défini un rapport qui peut être utilisé pendant le Report job. Un rapport " "contient une ou plusieurs sections." msgstr "" "Défini un rapport qui peut être utilisé pendant le Report job. Un rapport " "contient une ou plusieurs sections." #. REFERENCE: lire.xml #: config-spec.pot.pl:312 msgid "Défini une section d'un rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:310 #, fuzzy msgid "Définition de la section" msgstr "Défini une section d'un rapport." #: ../lib/Lire/LrCommand.pm:319 msgid "ERROR " msgstr "ERREUR " #: ../lib/Lire/UI/CompoundListWidget.pm:29 #: ../lib/Lire/UI/CompoundListWidget.pm:38 msgid "Edit" msgstr "Éditer" #: ../lib/Lire/UI.pm:87 #, perl-brace-format msgid "Editing {component}" msgstr "Édition de {component}" #: ../lib/Lire/LrCommand.pm:211 msgid "Email related options" msgstr "Options liées au courrier électronique" #. REFERENCE: lire.xml #: config-spec.pot.pl:28 msgid "Encodage utilisé dans le fichier de journal." msgstr "" #. REFERENCE: of_txt.xml #: config-spec.pot.pl:448 msgid "Encodage utilisé dans les rapports formattés." msgstr "" #: ../lib/Lire/LrCommand.pm:546 #, perl-brace-format msgid "Encountered {error_count} errors and ignored {ignored_count} lines." msgstr "{error_count} erreurs rencontrées et {ignored_count} lignes ignorées." #: ../lib/Lire/UI/StoreWindow.pm:152 msgid "Ends:" msgstr "Fin:" #: ../lib/Lire/UI/StoreWindow.pm:203 msgid "Enter the cleaning date in the form \"YYYY-MM-DD\":" msgstr "Entrez la date de nettoyage sous la forme \"YYYY-MM-DD\":" #. REFERENCE: lire.xml #: config-spec.pot.pl:266 msgid "Envoyer le rapport formatté par email." msgstr "" #: ../lib/Lire/UI.pm:308 #, perl-brace-format msgid "" "Error creating store:\n" " {error}" msgstr "" "Une erreur est survenue lors de la création du store:\n" " {error}" #: ../script/lr_spec2pot.in:158 #, perl-brace-format msgid "Error loading spec '{spec}': {error}" msgstr "" "Une erreur est survenue à l'ouverture de la spécification '{spec}': {error}" #: ../lib/Lire/UI.pm:338 #, perl-brace-format msgid "" "Error opening store:\n" " {error}" msgstr "" "Une erreur est survenue lors de l'ouverture du store:\n" " {error}" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:488 msgid "Errors" msgstr "Erreurs" #: ../lib/Lire/OutputFormats/Excel95.pm:38 msgid "Excel95 Spreadsheet" msgstr "Feuille de calcul Excel 95" #: ../lib/Lire/LrCommand.pm:543 #, perl-brace-format msgid "Extracted {dlf_count} DLF records on {line_count} lines." msgstr "{dlf_count} enregistrements DLF extraits sur {line_count} lignes." #. REFERENCE: lire.xml #: config-spec.pot.pl:282 #, fuzzy msgid "Fichier de configuration de rapport à utiliser." msgstr "Fichier de configuration de rapport à utiliser." #. REFERENCE: lire.xml #: config-spec.pot.pl:198 msgid "File d'entrée du répondeur" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:270 #, fuzzy msgid "File type of the generated report" msgstr "Gabarit de nom de fichier pour le ReportJob." #. REFERENCE: lire.xml #: config-spec.pot.pl:24 msgid "Filtre à appliquer au fichier de journal." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:314 #, fuzzy msgid "Filtres de la section" msgstr "Première section" #: ../lib/Lire/ReportParser/HTMLWriter.pm:116 msgid "First Section" msgstr "Première section" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:370 config-spec.pot.pl:410 config-spec.pot.pl:430 #, fuzzy msgid "First Y Variable" msgstr "Quatrième variable en Y" #: ../lib/Lire/OutputFormats/Excel95.pm:42 msgid "Format the report as a Excel95 spreadsheet." msgstr "Formatte le rapport dans une feuille de calcul Excel 95" #: ../script/lr_xml2report.in:17 msgid "" "Formats the XML report and save it in . If " " is omitted, the XML report will be read from STDIN. If " " is omitted, it will be output on STDOUT. Additional " "reports can be merged before formatting the report by using the --template " "and --merge options." msgstr "" "Formatte le rapport xml \"fichier de rapport\" et le sauve dans \"rapport " "final\". Si \"fichier de rapport\" est omis, le rapport XML sera lu de " "l'entrée standard. Si \"rapport final\" est omis, le rapport formatté sera " "émis sur la sortie standard. Des rapports additionnels peuvent être joints " "avant le formattage du rapport en utilisant les options \"--template\" et " "\"--merge\"." #: ../script/lr_xml2mail.in:20 msgid "" "Formats the XML report and sends it by email to the recipients " "specified as argument. Additional reports can be merged before formatting " "the report by using the --template and --merge options." msgstr "" "Formatte le rapport XML \"fichier de rapport\" et l'envoi par courrier " "électronique aux destinataires mis en arguments. Des rapports additionnels " "peuvent être joints avant le formattage du rapport en utilisant les options " "\"--template\" et \"--merge\"." #: ../lib/Lire/LrCommand.pm:757 #, perl-brace-format msgid "Formatting report as {format} and emailing it to {emails}..." msgstr "Formattage et envoi du rapport en {format} aux adresses {emails}..." #: ../lib/Lire/LrCommand.pm:714 #, perl-brace-format msgid "Formatting report as {format} in {file}..." msgstr "Formattage du rapport en {format} dans \"{file}\"..." #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:382 config-spec.pot.pl:422 msgid "Fourth Y Variable" msgstr "Quatrième variable en Y" #. REFERENCE: lire.xml #: config-spec.pot.pl:14 msgid "Gabarit de nom de fichier pour le ReportJob." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:112 msgid "Garder les fichiers intermédiaires" msgstr "" #: ../lib/Lire/LrCommand.pm:619 msgid "Generating XML report..." msgstr "Génération du rapport XML..." #. REFERENCE: of_html.xml #: config-spec.pot.pl:440 msgid "Générer ce rapport sur une page unique" msgstr "" #: ../lib/Lire/OutputFormats/HTML.pm:41 msgid "HTML Report with charts, if ploticus is available." msgstr "Rapport HTML avec diagrammes, si ploticus est disponible." #. REFERENCE: lire.xml #: config-spec.pot.pl:254 msgid "Horaires de génération des rapports" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:220 msgid "How are week numbers computed?" msgstr "Calcul de la numérotation des semaines" #. REFERENCE: lire.xml #: config-spec.pot.pl:274 #, fuzzy msgid "Identifiant" msgstr "Identifiant" #. REFERENCE: lire.xml #: config-spec.pot.pl:302 msgid "Identifiant du rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:132 msgid "Identifiant à utiliser pour le programme \"syslog\"" msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:141 msgid "Identifier" msgstr "Identifiant" #: ../lib/Lire/Config/XMLSpecListSpec.pm:142 msgid "" "Identifier that uniquely identifies this specification among the report " "configuration. When two reports are merged, specifications with the same " "identifier are merged together." msgstr "" "Symbole qui identifie cette spécification de façon unique à l'intérieur de " "la configuration du rapport. Lorsque deux rapports sont réunis, les " "spécifications au même nom sont fondues ensemble." #: ../lib/Lire/Config/XMLSpecListSpec.pm:147 msgid "" "If this parameter is set, its value will be used instead of the display " "title specified in the specification. This string will interpolate $name_ref " "with the parameter's value when the report is generated." msgstr "" "Quand ce paramètre est spécifié, sa valeur est utilisée au lieu du titre " "indiqué dans la spécification. Cette chaîne remplace \"$name_ref\" par la " "valeur du paramètre lorsque le rapport est généré." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:480 msgid "Ignored Lines" msgstr "Lignes ignorées" #. REFERENCE: lire.xml #: config-spec.pot.pl:216 msgid "" "Il est de bon aloi de restreindre les privilèges alloués aux processus au " "minimum. Lire ne requiert pas l'utilisation du compte \"root\" pour son " "fonctionnement normal. Il est donc conseillé de créer un compte UNIX dédié. " "Lire vérifie son id d'utilisateur à son démarrage et s'arrête s'il détermine " "qu'il tourne sur le compte du superutilisateur. Cette option vous permet de " "désactiver cette vérification à vos risques et périls." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:102 msgid "" "Il est maintenant possible de personnaliser la présentation de certains " "éléments des rapports HTML. La feuille de style par défaut de Lire pour le " "HTML assure une présentation adéquate mais cette option vous donne la " "possibilité d'utiliser votre propre feuille de style." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:252 msgid "" "Il est necessaire d'identifier les report jobs afin que Lire puisse les " "traiter correctement. Utilisez cette variable pour ce faire. NOTE: Cet " "identifiant ne peut contenir que des caracteres alphanumeriques, des tirets " "et des caracteres de soulignage." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:38 msgid "" "Il est nécessaire d'identifier les import jobs afin que Lire puisse les " "traiter correctement. Utilisez cette variable pour ce faire." msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:42 msgid "Import Jobs" msgstr "Jobs d'importation" #. REFERENCE: lire.xml #: config-spec.pot.pl:22 #, fuzzy msgid "ImportJobs configuré dans le store actuel." msgstr "ImportJobs configuré dans le store actuel." #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:451 msgid "Important:" msgstr "Important:" #. REFERENCE: lire.xml #: config-spec.pot.pl:184 msgid "" "Indique à Lire d'afficher les décomptes d'octets dans un format lisible. Une " "échelonnage binaire est opéré, de sorte que \"1Kb\" ait pour valeur \"1024 " "octets\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:202 msgid "Intervale de vérification de la file d'entrée du répondeur" msgstr "" #: ../lib/Lire/UI/CommandWidget.pm:10 msgid "Invalid command" msgstr "Commande invalide" #: ../lib/Lire/UI/DirectoryWidget.pm:10 msgid "Invalid directory" msgstr "Répertoire invalide" #: ../lib/Lire/UI/ExecutableWidget.pm:10 msgid "Invalid executable" msgstr "Exécutable invalide" #: ../lib/Lire/UI/FileWidget.pm:96 msgid "Invalid filename" msgstr "Nom de fichier invalide" #: ../script/lr_cron.in:27 #, perl-brace-format msgid "" "Invalid period '{period}'. Should be one of hourly, daily, weekly, monthly " "or yearly.\n" msgstr "" "Période \"{period}\" invalide. Devrait être \"hourly\", \"daily\", \"weekly" "\", \"monthly\" ou \"yearly\" respectivement pour horaire, quotidien, " "hebdomadaire, mensuel et annuel.\n" #. REFERENCE: schema:lire_import_stats #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:468 config-spec.pot.pl:504 msgid "Job Id" msgstr "Identifiant du Job" #. REFERENCE: schema:lire_import_stats #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:464 config-spec.pot.pl:500 msgid "Job Name" msgstr "Nom du Job" #: ../lib/Lire/LrCommand.pm:101 #, perl-brace-format msgid "Keeping temporary directory {tmpdir}" msgstr "Conservation du répertoire temporaire \"{tmpdir}\"" #. REFERENCE: lire.xml #: config-spec.pot.pl:158 msgid "" "L'adresse email à laquelle les utilisateurs du répondeur doivent répondre, " "si différente de la valeur donnée à \"lr_mail_from\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:154 msgid "" "L'adresse spécifiée dans le champ \"From\" des courriels contenant le " "rapport envoyé par le répondeur." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:246 msgid "" "La commande \"ps2pdf\" est nécessaire pour générer des rapports PDF. Elle " "fait partie de la distribution de Ghostscript. Consultez le manuel de " "l'utilisateur pour les adresses de téléchargement." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:280 msgid "" "La fréquence à laquelle cette planification de rapport sera exécutée. La " "valeur de ce paramètre peut être \"hourly\", \"daily\", \"weekly\", \"monthly" "\" or \"yearly\" (\"horaire\", \"quotidien\", \"hebdomadaire\",\"mensuel\" " "ou \"annuel\", respectivement). NOTE: pour générer des rapports " "hebdomadaires, mensuels ou annuels, au moins une planification de rapport " "quotidienne devra être disponible si vous nettoyer votre store DLF. Ce, " "parce que lorsqu'il ne peut trouver les données dans la base de donnée, Lire " "génère ces rapports par un algorithme de jonction dans lequel seuls les " "rapports quotidiens sont considérés." msgstr "" #. REFERENCE: ct_pie.xml #: config-spec.pot.pl:386 msgid "La variable des valeurs" msgstr "" #. REFERENCE: ct_pie.xml #: config-spec.pot.pl:388 msgid "" "La variable numérique qui sera utilisée pour déterminer les aires du " "diagramme." msgstr "" #: ../lib/Lire/OutputFormats/LaTeX.pm:38 msgid "LaTeX" msgstr "LaTeX" #: ../lib/Lire/OutputFormats/LaTeX.pm:42 msgid "LaTeX report with charts." msgstr "Rapport LaTeX avec diagrammes." #: ../lib/Lire/ReportParser/HTMLWriter.pm:119 msgid "Last Section" msgstr "Dernière section" #. REFERENCE: lire.xml #: config-spec.pot.pl:320 msgid "Le diagramme et le sous-rapport qui seront inclus dans la section." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:122 msgid "" "Le service UNIX standard syslog a plusieurs façon de catégoriser les " "messages de journal. Vous pouvez configurer le service syslog pour trier ces " "messages dans différents fichiers selon l'indicateur de facilité. Cette " "option vous permet de sélectionner la facilité que Lire utilisera. Consultez " "la page de manuel syslog.conf(5) pour plus d'information." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:134 msgid "" "Le service UNIX standard syslog permet d'indiquer un identifiant par lequel " "chaque ligne générée par Lire sera marquée. On recommande d'utiliser une " "chaîne de caractères courte et sans espace, comme par exemple \"lire\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:130 msgid "Le service UNIX syslog" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:328 msgid "Le titre de la section qui apparaîtra dans le rapport généré." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:332 msgid "Le titre qui apparaîtra dans le rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:262 msgid "Le type cible du rapport émis." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:260 msgid "" "Les OutputJobs permettent la génération de rapports sous diverses formes et " "en plusieurs formats. Plusieurs peuvent être programmés pour la même période." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:256 msgid "" "Les ReportJobs doivent portent sur une ou plusieurs périodes, chacune " "d'elles étant alors appelée \"planification de rapport\". Une planification " "de rapport vous permet de spécifier quel rapport sera formatté, sa " "configuration ainsi que sa fréquence de génération." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:284 msgid "" "Les fichiers de configuration de rapport sont des fichiers texte avec une " "syntaxe particulière décrivant le type d'informations affichées dans le " "rapport ainsi que sa présentation. Lire est fourni avec un fichier-type de " "configuration pour chaque superservice mais vous pouvez créer le vôtre " "accordé à vos besoins." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:200 msgid "" "Les modules du répondeur automatique de Lire extraient les fichiers journaux " "des courriels, traitent leur contenu et renvoient un courriel à leur " "émetteur. Lorsque le répondeur est activé, il vérifie la présence de " "courriels entrants dans ce répertoire. Consultez le manuel de l'utilisateur " "de Lire pour savoir comment configurer la distribution des courriels vers ce " "répertoire." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:56 msgid "Les requêtes doivent-elles être archivées?" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:68 msgid "" "Les répertoires contenant des initialiseurs de convertisseurs DLF (obsolète)." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:324 #, fuzzy msgid "Les superservices couverts dans cette section." msgstr "Les superservices couverts dans cette section." #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:390 msgid "Ligne de régression" msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:512 msgid "Line Number" msgstr "Numéro de ligne" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:508 msgid "Line Type" msgstr "Type de ligne" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:472 msgid "Lines Read" msgstr "Lignes lues" #: ../lib/Lire/UI/Prefs.pm:102 msgid "Lire Paths" msgstr "Chemins d'accès Lire" #: ../lib/Lire/UI/Prefs.pm:60 msgid "Lire Preferences" msgstr "Préférences de Lire" #: ../lib/Lire/ReportParser/HTMLWriter.pm:142 msgid "Lire Report" msgstr "Rapport Lire" #. REFERENCE: lire.xml #: config-spec.pot.pl:292 msgid "" "Lire assemble les données par \"superservices\", qui en gros sont des types " "de services. Cette option vous permet de sélectionner le type de données que " "ce report job devra traiter: web, base de données, email ou n'importe quel " "type affiché dans cette liste." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:272 msgid "" "Lire peut formatter ses rapports de différentes façons, du texte simple au " "PDF, plus joli et plus approprié pour l'impression." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:126 msgid "" "Lire peut générer beaucoup d'information de sortie lors de son " "fonctionnement. Si Lire fonctionne via un traitement automatisé comme le " "répondeur ou une tâche cron, il peut être plus approprié d'envoyer ces " "données dans le journal du système pour inspection ultérieure." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:264 msgid "" "Lire peut sauvegarder ses rapports formattés dans un fichier sur le disque " "ou bien l'envoyer par email à une adresse spécifiée. Cette option vous " "permet de déterminer cela." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:316 #, fuzzy msgid "List des filtres qui seront appliqués à cette section." msgstr "List des filtres qui seront appliqués à cette section." #. REFERENCE: lire.xml #: config-spec.pot.pl:308 #, fuzzy msgid "List des sections définies dans le rapport." msgstr "List des sections définies dans le rapport." #. REFERENCE: lire.xml #: config-spec.pot.pl:258 #, fuzzy msgid "List of OutputJobs" msgstr "List des OutputJobs" #: ../lib/Lire/Config/ReportSectionSpec.pm:45 msgid "List of filters that will be applied to this section." msgstr "List des filtres qui seront appliqués à cette section." #: ../lib/Lire/Config/ReportSpec.pm:44 msgid "List of sections defined in the report." msgstr "List des sections définies dans le rapport." #. REFERENCE: lire.xml #: config-spec.pot.pl:296 #, fuzzy msgid "Liste d'objets ReportConfig utilisés par ce store." msgstr "Liste d'objets ReportConfig utilisés par ce store." #. REFERENCE: lire.xml #: config-spec.pot.pl:60 msgid "Location of the archive" msgstr "Localisation de l'archive" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:516 msgid "Log Line" msgstr "Ligne de journal" #: ../lib/Lire/LrCommand.pm:484 #, perl-brace-format msgid "Log file was compressed using {algo}." msgstr "Le fichier journal était compressé à l'aide de {algo}." #. REFERENCE: lire.xml #: config-spec.pot.pl:58 msgid "" "Lorsque ce paramètre est activé, le répondeur gardera une copie de chaque " "message reçu dans le répertoire spécifié dans la paramètre " "\"lr_archive_dir\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:94 #, fuzzy msgid "" "Lorsque cette option est active, tous les messages de niveau \"debug\" et " "\"info\" seront dirigés vers stderr ou le journal du " "système - dépendamment de la façon dont Lire est configuré et de si vous " "utilisez la commande lr_run pour invoquer les commandes " "de Lire." msgstr "" "Lorsque cette option est active, tous les messages de niveau \"debug\" et " "\"info\" seront dirigés vers stderr ou le journal du " "système - dépendamment de la façon dont Lire est configuré et de si vous " "utilisez la commande lr_run pour invoquer les commandes " "de Lire." #. REFERENCE: lire.xml #: config-spec.pot.pl:62 msgid "" "Lorsque l'option \"lr_archive\" est active, le répertoire " "où les requêtes seront archivées." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:204 msgid "" "Lorsque le répondeur est activé, il vérifie souvent la présence de courriels " "dans la file d'entrée. Vous pouvez spécifier la fréquence de vérification " "ici, en minutes." msgstr "" #: ../lib/Lire/LrCommand.pm:255 msgid "" "Merge an additional report before formatting the report. This option can be " "used multipe times." msgstr "" "Joint un rapport additionnel avant le formattage du rapport. Cette option " "peut être indiquée plusieurs fois." #: ../lib/Lire/LrCommand.pm:245 msgid "Merging options" msgstr "Options de jonction" #: ../lib/Lire/LrCommand.pm:672 #, perl-brace-format msgid "Merging reports '{reports}'..." msgstr "Jonction des rapports \"{reports}\"..." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:520 msgid "Message" msgstr "Message" #: ../lib/Lire/Error.pm:133 #, perl-brace-format msgid "Missing '{argument}' argument.\n" msgstr "Argument '{argument}' manquant.\n" #. REFERENCE: lire.xml #: config-spec.pot.pl:250 #, fuzzy msgid "Name of the ReportJob." msgstr "Nom de l'ImportJob." #. REFERENCE: lire.xml #: config-spec.pot.pl:340 #, fuzzy msgid "Name of the tai64nlocal(1) program." msgstr "Nom du programme tai64nlocal(1)" #: ../lib/Lire/OutputFormats/XML.pm:38 msgid "" "Native XML format. This keeps the report in Lire Report Markup Language." msgstr "" "Format XML natif. Conserve les rapports en Lire Report Markup Language." #: ../lib/Lire/UI.pm:175 ../lib/Lire/UI.pm:195 msgid "New..." msgstr "Nouveau..." #: ../lib/Lire/ReportParser/HTMLWriter.pm:515 msgid "Next" msgstr "Suivant" #: ../lib/Lire/ReportParser/HTMLWriter.pm:122 msgid "Next Page" msgstr "Page suivante" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:41 msgid "No analyser" msgstr "Aucun analyseur" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:42 msgid "No analyser will be used." msgstr "Aucun analyseur ne sera utilisé." #: ../lib/Lire/LrCommand.pm:566 #, perl-brace-format msgid "" "No default report configuration template defined for DLF converter " "\"{converter}.\"." msgstr "" "Aucun gabarit de configuration de rapport par défaut défini pour le " "convertisseur DLF \"{converter}.\"." #: ../lib/Lire/ReportParser/HTMLWriter.pm:281 msgid "No description." msgstr "Aucune description." #: ../lib/Lire/UI/Prefs.pm:198 ../lib/Lire/UI/CompoundWidget.pm:231 msgid "No help available." msgstr "Aucune aide disponible." #: ../lib/Lire/LrCommand.pm:640 #, perl-brace-format msgid "No report configuration template: {template}." msgstr "Aucun gabarit de configuration de rapport: {template}." #: ../lib/Lire/ReportParser/HTMLWriter.pm:408 msgid "No subreports were generated for this section." msgstr "Cette section ne contient aucun sous-rapport." #: ../lib/Lire/LrCommand.pm:579 #, perl-brace-format msgid "No such DLF converter: {converter}." msgstr "Pas de convertisseur DLF de ce nom: \"{converter}\"." #: ../lib/Lire/LrCommand.pm:693 #, perl-brace-format msgid "No such output format: {format}." msgstr "Pas de format de sortie de ce nom: \"{format}\"." #. REFERENCE: lire.xml #: config-spec.pot.pl:36 #, fuzzy msgid "Nom de l'ImportJob." msgstr "Nom de l'ImportJob." #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:447 msgid "Note:" msgstr "Note:" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:478 msgid "Number of DLF records created during the job." msgstr "Nombre d'enregistrements DLF créés pendant ce job." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:490 msgid "Number of errors encountered during that job." msgstr "Nombre d'erreurs survenues pendant ce job." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:482 msgid "Number of lines ignored during that ImportJob." msgstr "Nombre de lignes ignorées pendant cet ImportJob." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:486 msgid "Number of lines saved for later processing during that ImportJob." msgstr "" "Nombre de lignes sauvegardées pour traitement ultérieur pendant cet " "ImportJob." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:474 msgid "Number of log lines processed during that job." msgstr "Nombre de lignes traitées pendant ce job." #. REFERENCE: lire.xml #. REFERENCE: of_html.xml #: config-spec.pot.pl:48 config-spec.pot.pl:72 config-spec.pot.pl:74 #: config-spec.pot.pl:76 config-spec.pot.pl:78 config-spec.pot.pl:80 #: config-spec.pot.pl:82 config-spec.pot.pl:84 config-spec.pot.pl:86 #: config-spec.pot.pl:88 config-spec.pot.pl:90 config-spec.pot.pl:104 #: config-spec.pot.pl:106 config-spec.pot.pl:108 config-spec.pot.pl:172 #: config-spec.pot.pl:176 config-spec.pot.pl:206 config-spec.pot.pl:208 #: config-spec.pot.pl:210 config-spec.pot.pl:218 config-spec.pot.pl:224 #: config-spec.pot.pl:230 config-spec.pot.pl:232 config-spec.pot.pl:234 #: config-spec.pot.pl:236 config-spec.pot.pl:348 config-spec.pot.pl:350 #: config-spec.pot.pl:352 config-spec.pot.pl:438 msgid "Obsolete" msgstr "Obsolète" #: ../lib/Lire/LrCommand.pm:203 msgid "Only print errors." msgstr "Affiche seulement les erreurs." #: ../lib/Lire/UI.pm:177 ../lib/Lire/UI.pm:197 msgid "Open..." msgstr "Ouvrir..." #: ../lib/Lire/UI/Prefs.pm:101 msgid "Operational Preferences" msgstr "Paramètres fonctionnels" #. REFERENCE: lire.xml #: config-spec.pot.pl:10 #, fuzzy msgid "Options spécifiques au fichier de destination choisi." msgstr "Options spécifiques au fichier de destination choisi." #: ../lib/Lire/LrCommand.pm:228 msgid "Output format options" msgstr "Options du format de sortie" #. REFERENCE: lire.xml #: config-spec.pot.pl:124 #, fuzzy msgid "Où envoyer les messages de type progress/debug/warning/error" msgstr "Où envoyer les messages de type progress/debug/warning/error" #: ../lib/Lire/OutputFormats/PDF.pm:37 msgid "PDF" msgstr "PDF" #: ../lib/Lire/OutputFormats/PDF.pm:41 msgid "PDF report with charts." msgstr "Rapport PDF avec diagrammes." #: ../lib/Lire/Config/XMLSpecListSpec.pm:170 msgid "" "Parameters for a chart that should be generated from this subreport's data." msgstr "" "Paramètres un diagramme qui devrait être généré par les données de ce sous-" "rapport." #: ../lib/Lire/Config/XMLSpecListSpec.pm:165 msgid "" "Parameters for the charts that should be generated from this subreport's data" msgstr "" "Paramètres pour les diagrammes qui devraient être générés par les données de " "ce sous-rapport." #. REFERENCE: lire.xml #: config-spec.pot.pl:116 msgid "Paramétrage de LaTeX" msgstr "" #: ../lib/Lire/LrCommand.pm:534 #, perl-brace-format msgid "Parsing log file using {converter} DLF Converter..." msgstr "" "Analyze du fichier journal à l'aide du convertisseur DLF \"{converter}\"..." #. REFERENCE: lire.xml #: config-spec.pot.pl:50 #, fuzzy msgid "Path to Lambda" msgstr "Chemin d'accès à Lambda" #. REFERENCE: lire.xml #: config-spec.pot.pl:226 #, fuzzy msgid "Path to odvips" msgstr "Chemin d'accès à odvips" #. REFERENCE: lire.xml #: config-spec.pot.pl:244 #, fuzzy msgid "Path to ps2pdf" msgstr "Chemin d'accès à ps2pdf" #. REFERENCE: lire.xml #: config-spec.pot.pl:18 #, fuzzy msgid "Path to the gs(1) program." msgstr "Chemin d'accès à gs(1)" #. REFERENCE: lire.xml #: config-spec.pot.pl:20 #, fuzzy msgid "Path to the gzip(1) program." msgstr "Chemin d'accès à gzip(1)" #. REFERENCE: lire.xml #: config-spec.pot.pl:32 msgid "Path to the log file that will be processed." msgstr "Chemin d'accès au fichier journal à traiter." #. REFERENCE: lire.xml #: config-spec.pot.pl:238 #, fuzzy msgid "Path to the ploticus(1) program." msgstr "Chemin d'accès à ploticus(1)" #. REFERENCE: lire.xml #: config-spec.pot.pl:334 #, fuzzy msgid "Path to the sendmail(1) program." msgstr "Chemin d'accès à sendmail(1)" #. REFERENCE: lire.xml #: config-spec.pot.pl:344 #, fuzzy msgid "Path to the tar(1) program." msgstr "Chemin d'accès à tar(1)" #. REFERENCE: lire.xml #: config-spec.pot.pl:114 msgid "" "Pendant ses traitements, Lire génère des fichiers intermédiaires qu'il " "efface lorsque plus nécessaires. Si vous voulez étudier ou déboguer le " "fonctionnement de Lire, il vous est possible de l'empêcher de les effacer en " "activant cette option. Les fichiers seront conservés dans le répertoire " "indiqué dans la variable d'environnement \"TMPDIR\"." msgstr "" #: ../lib/Lire/ChartTypes/Pie.pm:35 msgid "Pie chart" msgstr "Diagramme en secteurs" #: ../lib/Lire/OutputFormats/Text.pm:37 msgid "Plain Text" msgstr "Texte simple" #: ../lib/Lire/OutputFormats/Text.pm:41 msgid "Plain Text format." msgstr "Format texte simple." #: ../lib/Lire/ChartTypes/VBars.pm:35 msgid "Plot one or two variables as bars." msgstr "Représente une ou deux variables en barres." #: ../lib/Lire/ChartTypes/Lines.pm:35 msgid "Plot one to four variable as lines against another." msgstr "" "Représente de une à quatre variables en lignes alignées l'une contre l'autre." #: ../lib/Lire/ChartTypes/Stack.pm:35 msgid "Plot one to four variable stacked one over the other." msgstr "Représente de une à quatre variables empilées l'une sur l'autre." #. REFERENCE: lire.xml #: config-spec.pot.pl:64 msgid "Police utilisée dans les diagrammes" msgstr "" #: ../lib/Lire/OutputFormats/PS.pm:34 msgid "PostScript" msgstr "PostScript" #: ../lib/Lire/OutputFormats/PS.pm:38 msgid "PostScript report with charts." msgstr "Rapport PostScript avec diagrammes." #. REFERENCE: lire.xml #: config-spec.pot.pl:228 msgid "" "Pour générer des rapports en PostScript ou en PDF, vous devez avoir \"odvips" "\", la version Omega de \"dvips\". Cette commande est fournie avec la " "distribution TeTeX depuis sa version 0.9. Consultez le manuel de " "l'utilisateur pour les informations de télécharment." msgstr "" #: ../lib/Lire/LrCommand.pm:261 ../lib/Lire/LrCommand.pm:280 msgid "Pre Lire 2.0 report configuration file." msgstr "Fichier de configuration antérieur à Lire 2.0." #: ../lib/Lire/UI.pm:169 msgid "Preferences..." msgstr "Préférences..." #. REFERENCE: lire.xml #: config-spec.pot.pl:214 msgid "Prevent Lire from being run as root" msgstr "Empêcher Lire d'être exécuté avec les privilèges du superutilisateur" #: ../lib/Lire/ReportParser/HTMLWriter.pm:509 msgid "Previous" msgstr "Précédent" #: ../lib/Lire/ReportParser/HTMLWriter.pm:120 msgid "Previous Page" msgstr "Page précédente" #: ../lib/Lire/LrCommand.pm:198 msgid "Print Lire version and exit." msgstr "Affiche la version de Lire et termine." #: ../lib/Lire/LrCommand.pm:193 msgid "" "Print usage information and exit. If \"report-templates\", \"output-formats" "\" or \"dlf-converters\" is given as argument, the command will print an " "information list for that object type." msgstr "" "Affiche l'information d'utilisation et se termine. Si \"report-templates\", " "\"output-formats\" ou \"dlf-converters\" sont indiqués comme arguments, la " "commande affichera la liste des valeurs disponibles pour les gabarits, les " "formats de sortie et les convertisseurs DLF." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:460 msgid "Processing Time" msgstr "Heure de traitement" #: ../lib/Lire/UI/Prefs.pm:104 msgid "Program Paths" msgstr "Chemins d'accès utilitaires" #: ../lib/Lire/UI/PluginWidget.pm:122 #, perl-brace-format msgid "Properties for {plugin}" msgstr "Propriétés pour {plugin}" #. REFERENCE: lire.xml #: config-spec.pot.pl:136 msgid "Quel logo afficher dans l'en-tête des rapports?" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:140 msgid "" "Quelle URI devrait être pointée par le logo affiché dans vos en-têtes de " "rapports." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:100 msgid "" "Quelle feuille de style CSS doit être utilisée pour vos rapports en HTML ?" msgstr "" #: ../lib/Lire/UI.pm:171 msgid "Quit" msgstr "Quitter" #: ../lib/Lire/UI/StoreWindow.pm:154 msgid "Records:" msgstr "Enregistrements:" #. REFERENCE: lire.xml #: config-spec.pot.pl:54 config-spec.pot.pl:96 config-spec.pot.pl:178 #: config-spec.pot.pl:196 #, fuzzy msgid "Remplacé dans logsource." msgstr "Remplacé dans logsource." #. REFERENCE: lire.xml #: config-spec.pot.pl:110 config-spec.pot.pl:164 config-spec.pot.pl:166 #: config-spec.pot.pl:174 #, fuzzy msgid "Remplacé dans report_output." msgstr "Remplacé dans report_output." #: ../lib/Lire/UI/StoreWindow.pm:54 msgid "Report Configurations" msgstr "Configurations de rapport" #: ../lib/Lire/UI/StoreWindow.pm:47 msgid "Report Jobs" msgstr "Jobs de rapport" #: ../lib/Lire/ReportParser/LaTeXWriter.pm:164 #, perl-brace-format msgid "Report for {start} -- {end}" msgstr "Rapport de {start} à {end}" #: ../lib/Lire/ReportParser/HTMLWriter.pm:531 #, perl-brace-format msgid "Report generated on: {date}" msgstr "Date de génération: {date}" #: ../lib/Lire/ReportParser/LaTeXWriter.pm:166 #, perl-brace-format msgid "Report generated {date}" msgstr "Date de génération: {date}" #: ../lib/Lire/LrCommand.pm:275 msgid "Report generation options" msgstr "Options de génération des rapports" #: ../lib/Lire/Config/ReportSpec.pm:36 msgid "Report's identifier" msgstr "Identifiant du rapport" #: ../lib/Lire/Config/ReportSpec.pm:43 msgid "Report's sections" msgstr "Sections du rapport" #: ../lib/Lire/Config/ReportSpec.pm:39 msgid "Report's title" msgstr "Titre du rapport" #. REFERENCE: lire.xml #: config-spec.pot.pl:248 #, fuzzy msgid "ReportJobs configurés dans le store actuel." msgstr "Fichier de configuration de rapport à utiliser." #: ../lib/Lire/ReportParser/HTMLWriter.pm:544 #, perl-brace-format msgid "Reporting on period: {period}" msgstr "Période couverte: {period}" #: ../lib/Lire/UI/Prefs.pm:99 msgid "Reports" msgstr "Rapports" #: ../lib/Lire/UI/Prefs.pm:100 msgid "Responder Preferences" msgstr "Paramètres du répondeur" #: ../lib/Lire/LrCommand.pm:614 msgid "Running analysers..." msgstr "Exécution des analyseurs..." #. REFERENCE: lire.xml #: config-spec.pot.pl:98 #, fuzzy msgid "Répertoires contenant des spécifications de filtres." msgstr "Répertoires contenant des spécifications de filtres." #. REFERENCE: lire.xml #: config-spec.pot.pl:212 msgid "Répertoires contenant les gabarits de spécification de rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:240 msgid "Répertoires contenant les initialiseurs de plugins." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:180 #, fuzzy msgid "Répertoires contenant les spécifications de rapports." msgstr "Répertoires contenant des spécifications de filtres." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:484 msgid "Saved Lines" msgstr "Lignes sauvegardées" #: ../lib/Lire/ChartTypes/Scat.pm:35 msgid "Scatterplot of two variables with optional regression line." msgstr "" "Nuage de points pour deux variables avec ligne de régression optionnelle." #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:374 config-spec.pot.pl:414 config-spec.pot.pl:434 #, fuzzy msgid "Seconde variable en Y" msgstr "Seconde variable en Y" #: ../lib/Lire/Config/ReportSpec.pm:46 msgid "Section definition" msgstr "Définition de la section" #: ../lib/Lire/Config/ReportSectionSpec.pm:38 msgid "Section's Superservice" msgstr "Superservice de la section" #: ../lib/Lire/Config/ReportSectionSpec.pm:51 msgid "Section's content" msgstr "Contenu de la section" #: ../lib/Lire/Config/ReportSectionSpec.pm:44 msgid "Section's filters" msgstr "Filtres de la section" #: ../lib/Lire/Config/ReportSectionSpec.pm:34 msgid "Section's title" msgstr "Titre de la section" #. REFERENCE: lire.xml #: config-spec.pot.pl:306 #, fuzzy msgid "Sections du rapport" msgstr "Contenu de la section" #: ../lib/Lire/UI/CommandWidget.pm:14 msgid "Select a Command" msgstr "Choisissez une commande" #: ../lib/Lire/UI/DirectoryWidget.pm:18 msgid "Select a Directory" msgstr "Choisissez un répertoire" #: ../lib/Lire/UI/FileWidget.pm:100 msgid "Select a File" msgstr "Choisissez un fichier" #: ../lib/Lire/UI/ExecutableWidget.pm:14 msgid "Select an Executable" msgstr "Choisissez un exécutable" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:80 #, perl-brace-format msgid "" "Select the analyser to use to create {schema} DLF records. If you select " "'none', no records will be created. Otherwise, the selected analyser will be " "run after each ImportJob that created records in the Dlf stream used by the " "analyser." msgstr "" "Choisissez l'analyseur à utiliser pour créer des enregistrement DLF " "{schema}. Si vous sélectionnez \"aucun\", alors aucun enregistrement ne sera " "créé. Autrement, l'analyseur choisi sera exécuté après chaque ImportJob qui " "aura créé des enregistrement dans le stream DLF utilisé par l'analyseur." #: ../lib/Lire/LrCommand.pm:236 msgid "Select the output format. Default to \"txt\"" msgstr "Choisissez le format de sortie. La valeur par défaut est \"txt\"." #: ../lib/Lire/LrCommand.pm:285 msgid "" "Select the report configuration template that should be used for generating " "the report." msgstr "" "Choisissez le gabarit de configuration de rapport à utiliser pour générer le " "rapport." #: ../lib/Lire/LrCommand.pm:249 msgid "" "Select the report configuration template that should be used for merging the " "reports. This option is required if you use the --merge option." msgstr "" "Choisissez le gabartit de configuration de rapport à utiliser pour joindre " "les rapports. Cette option est obligatoire si vous utilisez l'option \"--" "merge\"." #: ../lib/Lire/LrCommand.pm:266 msgid "" "Selects the superservice for which the report configuration file is made." msgstr "" "Sélectionner le superservice auquel le fichier de configuration de rapport " "correspond." #: ../lib/Lire/LrCommand.pm:214 msgid "Sets the email's subject." msgstr "Défini le sujet des courriels." #: ../script/lr_log2mail.in:22 msgid "Sets the log file to convert instead of reading it from STDIN." msgstr "" "Défini le fichier journal à convertir au lieu de le lire de l'entrée " "standard." #. REFERENCE: of_html.xml #: config-spec.pot.pl:442 msgid "" "Si vous désirez voir apparaître votre rapport sur une seule page, activez " "cette option. Autrement un document à plusieurs pages sera généré." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:368 msgid "" "Si vous indiquez une variable numérique, elle sera utilisée pour l'axe des X " "à la place de la variable \"case_var\"." msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:392 msgid "Spécifie si une ligne de régression sera dessinée ou non." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:456 msgid "Start Time" msgstr "Heure de début" #: ../lib/Lire/UI/StoreWindow.pm:150 msgid "Starts:" msgstr "Début:" #. REFERENCE: lire.xml #: config-spec.pot.pl:268 msgid "Store the formatted output into a file." msgstr "Placer la sortie formattée dans un fichier." #: ../lib/Lire/UI/StoreWindow.pm:75 msgid "Store: " msgstr "Store: " #. REFERENCE: lire.xml #: config-spec.pot.pl:6 #, fuzzy msgid "Sujet du courriel contenant le rapport." msgstr "Sujet du courriel contenant le rapport." #. REFERENCE: lire.xml #: config-spec.pot.pl:322 #, fuzzy msgid "Superservice de la section" msgstr "Les superservices couverts dans cette section." #. REFERENCE: lire.xml #: config-spec.pot.pl:290 #, fuzzy msgid "Sélectionner le superservice pour ce rapport." msgstr "Sélectionner le superservice pour ce rapport." #: ../lib/Lire/ReportParser/HTMLWriter.pm:114 #: ../lib/Lire/ReportParser/HTMLWriter.pm:426 #: ../lib/Lire/ReportParser/HTMLWriter.pm:431 #: ../lib/Lire/ReportParser/HTMLWriter.pm:503 msgid "Table Of Contents" msgstr "Table des matières" #. REFERENCE: lire.xml #: config-spec.pot.pl:144 config-spec.pot.pl:160 msgid "Texte d'avis de non-responsabilité du répondeur automatique" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:148 msgid "Texte d'explication du répondeur automatique" msgstr "" #: ../lib/Lire/LrCommand.pm:654 msgid "The -U option is required with --report-cfg" msgstr "L'option \"-U\" est requise avec \"--report-cfg\"" #: ../lib/Lire/Config/ChartSpec.pm:35 msgid "" "The basename of the chart. An extension will be appended based on the " "chart's format. If this attribute isn't set, the Subreport'id will be used." msgstr "" "Le nom du diagramme. L'extension qui y sera ajoutée en fonction de son " "format. Si cet attribut n'est pas spécifié, l'identifiant du sous-rapport " "sera utilisé à la place." #: ../lib/Lire/Config/ChartSpec.pm:49 msgid "" "The categorical variable that will be used to select the case that will make " "the chart's data." msgstr "" "La variable catégorique qui sera utilisée pour déterminer les données à " "représenter sur le diagramme." #: ../lib/Lire/Config/ReportSectionSpec.pm:52 msgid "The chart and subreport that will be included in this section." msgstr "Le diagramme et le sous-rapport qui seront inclus dans la section." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:518 msgid "The content of the log line." msgstr "Le contenu de la ligne de journal." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:462 msgid "The duration of the job." msgstr "La durée du job." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:506 msgid "" "The job id in which that line was processed. This is the job name plus the " "timestamp of the start of the job. " msgstr "" "L'identifiant du job pendant lequel cette ligne a été traitée. Il s'agit du " "nom du job ajouté de l'horodatage du début du job." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:470 msgid "" "The job id to which the stats relate to. This is the job name plus the " "timestamp of the start of the job. The job id makes it possible to " "distinguish between different run of the same scheduled import or analysis " "job. " msgstr "" "L'identifiant du job à laquelle les statistiques se réfèrent. Il s'agit du " "nom du job ajouté du pointage du temps de démarrage du job. Cela permet de " "faire la distinction entre les différentes exécutions de la même " "planification d'ImportJob ou d'AnalysisJob." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:514 msgid "The log line number." msgstr "Le numéro de ligne dans le journal." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:502 msgid "The name of the ImportJob to which that log line is related." msgstr "Le nom de l'ImportJob auquel cette ligne de journal est relative." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:466 msgid "The name of the job." msgstr "Le nom du job." #: ../lib/Lire/Config/ReportSectionSpec.pm:35 msgid "The section's title that will appear in the generated report." msgstr "Le titre de la section qui apparaîtra dans le rapport généré." #: ../lib/Lire/Config/ReportSectionSpec.pm:39 msgid "The superservices that is used by this section." msgstr "Les superservices couverts dans cette section." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:498 msgid "The time at which that log line was processed." msgstr "Le moment auquel cette ligne de journal a été traitée." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:458 msgid "The time at which the job was started." msgstr "L'heure à laquelle le job a démarré" #: ../lib/Lire/Config/ChartSpec.pm:40 msgid "The title that will appear on the chart." msgstr "Le titre qui apparaîtra dans le diagramme." #: ../lib/Lire/Config/ChartSpec.pm:44 msgid "The type of charts to generate. Chart types are plugins." msgstr "" "Le type de diagrammes à générer. Les types de diagrammes sont des plugins." #: ../lib/Lire/ReportParser/HTMLWriter.pm:310 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:280 msgid "There is no entries in this table." msgstr "Aucune entrée dans cette table." #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:454 msgid "This Dlf schema is used to store ImportJob and AnalysisJob statistics." msgstr "" "Ce schema Dlf est utilisé pour emmagasiner les statistiques liées aux " "ImportJobs et aux AnalysisJobs." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:494 msgid "" "This Dlf schema is used to store information related to importation and " "analysis jobs. It is this Dlf stream that will contains the lines that were " "marked for continuation, that were ignored or that had errors during an " "importation process. " msgstr "" "Ce schema DLF est utilisé pour emmagasiner les informations reliées aux jobs " "d'importation et d'analyse. C'est ce stream DLF qui contiendra les lignes " "marquées comme à compléter, ignorées ou erronées pendant le processus " "d'importation." #: ../lib/Lire/LrCommand.pm:742 msgid "This command requires the MIME::Tools CPAN module." msgstr "Cette commande requiert le module MIME::Tools de CPAN." #: ../lib/Lire/Config/DlfStreamSpec.pm:68 msgid "" "This configures the analysers that should be run on this DlfStream as well " "as the number of days of data to keep." msgstr "" "Ceci configure les analyseurs qui seront appliqués sur ce DlfStream ainsi " "que le nombre de jours de données à conserver." #: ../lib/Lire/DlfSchema.pm:158 msgid "" "This field contains an identifier relating the record to the process\n" "that created it.\n" msgstr "" "Ce champ contient un nombre entier indiquant la relation entre\n" "l'enregistrement au processus qui l'a créé.\n" #: ../lib/Lire/DlfSchema.pm:150 msgid "" "This field contains an integer which uniquely identify this DLF record\n" "in the stream.\n" msgstr "" "Ce champ contient un nombre entier qui identifie cet enregistrement DLF\n" "dans le stream de façon unique.\n" #: ../lib/Lire/Config/ReportSpec.pm:37 msgid "This identifier can be used to refer to this report configuration." msgstr "" "Cet identifiant peut être utilisé comme référence à la configuration de ce " "rapport." #: ../lib/Lire/LrCommand.pm:396 msgid "This option is obsolete." msgstr "Cette option est obsolète." #: ../lib/Lire/LrCommand.pm:700 msgid "This output format has missing requirements:" msgstr "Ce format de sortie a des pré-requis manquants:" #: ../lib/Lire/Config/DlfStreamSpec.pm:41 msgid "" "This parameter states how many days of DLF records you want to keep in the " "DlfStore. Records older than this number of days will be deleted. Use 0 to " "never expires records." msgstr "" "Ce paramètre indique le nombre de jours d'enregistrement DLF vous désirez " "conserver dans le DlfStore. Les enregistrements anciens de plus que ce " "nombre de jours seront effacés. Indiquez \"0\" pour désactiver l'expiration " "des enregistrements." #: ../lib/Lire/ReportParser/HTMLWriter.pm:363 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:214 #, perl-brace-format msgid "This report is missing: {reason}" msgstr "Ce rapport est manquant: {reason}" #. REFERENCE: lire.xml #: config-spec.pot.pl:70 #, fuzzy msgid "This variable is superseded by plugins_init_path." msgstr "Cette variable est remplacée par plugins_init_path." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:496 msgid "Timestamp" msgstr "Horodatage" #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:449 msgid "Tip:" msgstr "Astuce:" #. REFERENCE: lire.xml #: config-spec.pot.pl:326 msgid "Titre de la section" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:330 msgid "Titre du rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:52 msgid "" "To generate DVI, PostScript or PDF reports you need Lambda which is the " "Omega version of LaTeX. It is bundled with the TeTeX distribution since " "version 0.9. See the User Manual for download locations." msgstr "" "Pour générer des rapports en DVI, en PostScript ou en PDF, vous devez avoir " "Lambda, la version Omega de LaTeX. Il est fourni avec la distribution TeTeX " "depuis sa version 0.9. Consultez le manuel de l'utilisateur pour les " "informations de télécharment." #: ../lib/Lire/ReportParser/HTMLWriter.pm:221 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:334 #, perl-brace-format msgid "Total for {nrecords} records" msgstr "Total pour {nrecords} enreg." #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:378 config-spec.pot.pl:418 msgid "Troisième variable en Y" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:44 #, fuzzy msgid "Type of the logfile." msgstr "Le contenu de la ligne de journal." #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:360 msgid "" "Une variable numérique pour laquelle la distribution sera tracée pour les " "cas choisis pour \"case_var\"." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:542 msgid "Unknown Period" msgstr "période indéfinie" #: ../lib/Lire/Error.pm:154 #, perl-brace-format msgid "Unknown command: '{command}'.\n" msgstr "Commande inconnue: '{command}'.\n" #: ../lib/Lire/LrCommand.pm:387 #, perl-brace-format msgid "Unknown help section: {section}" msgstr "Section d'aide inconnue: {section}" #: ../lib/Lire/UI/ListWidget.pm:117 ../lib/Lire/UI/ListWidget.pm:145 msgid "Up" msgstr "Haut" #: ../script/lr_cron.in:21 msgid "Usage: lr_cron \n" msgstr "Utilisation: lr_cron \n" #: ../script/lr_report_cfg2xml.in:22 msgid "Usage: lr_report_cfg2xml \n" msgstr "" "Utilisation: lr_report_cfg2xml " "\n" #: ../script/lr_spec2pot.in:27 msgid "" "Usage: lr_spec2pot [--cfgspecdir ]*\n" " [--reportsdir ]*\n" " [--filtersdir ]*\n" " [--pluginsdir ]*\n" " [--schemasdir ]* +\n" msgstr "" "Utilisation: lr_spec2pot [--cfgspecdir ]*\n" " [--reportsdir ]*\n" " [--filtersdir ]*\n" " [--pluginsdir ]*\n" " [--schemasdir ]* +\n" #: ../lib/Lire/LrCommand.pm:370 #, perl-brace-format msgid "Usage: {program} {usage}" msgstr "Utilisation: {program} {usage}" #: ../lib/Lire/LrCommand.pm:581 msgid "Use --help dlf-converters to list available converters" msgstr "" "Utilisez l'option \"--help dlf-converters\" pour lister les différents " "convertisseurs disponibles." #: ../lib/Lire/LrCommand.pm:695 msgid "Use --help output-formats to list available formats." msgstr "" "Utilisez l'option \"--help output-formats\" pour lister les différents " "formats de sortie disponibles." #: ../lib/Lire/LrCommand.pm:642 msgid "Use --help report-templates to list available templates." msgstr "" "Utilisez l'option \"--help report-templates\" pour lister les différents " "gabarits disponibles." #. REFERENCE: of_html.xml #: config-spec.pot.pl:444 #, fuzzy msgid "Use XHTML 1.0 syntax" msgstr "Utiliser la syntaxe XHTML 1.0" #: ../lib/Lire/LrCommand.pm:568 msgid "Use the --template option." msgstr "Utilisez l'option \"--template\"." #. REFERENCE: lire.xml #: config-spec.pot.pl:30 msgid "" "Utilisez ce paramètre au cas où vos fichiers journaux sont encodés dans une " "format différent de votre système." msgstr "" #. REFERENCE: of_txt.xml #: config-spec.pot.pl:450 msgid "" "Utilisez ce paramètre au cas où vous désirez formatter vos rapports dans un " "encodage différent de celui utilisé par votre système." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:66 #, fuzzy msgid "" "Utilisez cette option pour contrôler la fonte que Ploticus utilisera pour le " "rendu des caractères. Les fontes disponibles dépendent du format d'image " "choisi. Consultez la documentation pour plus de détails." msgstr "" "Utilisez cette option pour contrôler la fonte que Ploticus utilisera pour le " "rendu des caractères. Les fontes disponibles dépendent du format d'image " "choisi. Consultez la documentation pour plus de détails." #. REFERENCE: lire.xml #: config-spec.pot.pl:156 msgid "Valeur de l'en-tête de courriel \"Reply-To\"" msgstr "" #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:358 #, fuzzy msgid "Variable" msgstr "Variable" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:366 msgid "Variable numérique des X" msgstr "" #: ../lib/Lire/LrCommand.pm:330 msgid "WARNING " msgstr "AVERTISSEMENT " #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:448 msgid "Warning:" msgstr "Avertissement:" #. REFERENCE: of_html.xml #: config-spec.pot.pl:446 msgid "" "XHTML is the modern form of HTML. XHTML files are actually XML files with an " "HTML vocabulary. Since XHTML 1.0 is just a little bit more than HTML 4.01, " "the result displayed will not change considerably but certain people like to " "live on the bleeding edge..." msgstr "" "XHTML est la forme actuelle de HTML. Les fichiers XHTML sont en réalité des " "fichiers XML avec un vocabulaire HTML. Puisque XHTML 1.0 n'est tout au plus " "qu'une variante améliorée de HTML 4.01, le résultat affiché ne devrait pas " "varier beaucoup. Toutefois certains aiment vivre au fait des technologies..." #: ../lib/Lire/OutputFormats/XML.pm:34 msgid "XML" msgstr "XML" #: ../script/lr_log2mail.in:30 ../script/lr_xml2mail.in:26 msgid "You need at least one email argument." msgstr "Au moins une adresse de courriel est requise comme argument." #: ../lib/Lire/LrCommand.pm:659 msgid "You need to use the --template option to merge reports." msgstr "Vous devez utiliser l'option \"--template\" pour joindre des rapports." #: ../lib/Lire/LrCommand.pm:756 #, perl-brace-format msgid "Your {format} report." msgstr "Votre rapport en {format}." #: ../script/lr_xml2mail.in:19 msgid "[] +" msgstr "[] +" #: ../script/lr_xml2report.in:16 msgid "[] [ []]" msgstr "[] +" #: ../script/lr_log2mail.in:23 msgid "[] +" msgstr "[] +" #: ../script/lr_log2report.in:18 msgid "[] [ []]" msgstr "" "[] [ []]" #: ../lib/Lire/UI/StoreWindow.pm:163 msgid "[Clean]" msgstr "[Nettoyer]" #: ../lib/Lire/UI/StoreWindow.pm:161 msgid "[Configure]" msgstr "[Configurer]" #: ../lib/Lire/ReportParser/LaTeXWriter.pm:330 msgid "continued on next page" msgstr "poursuivi à la page suivante" #: ../lib/Lire/Error.pm:69 ../lib/Lire/Error.pm:78 #, perl-brace-format msgid "could not open '{file}' for reading: {error}" msgstr "impossible d'ouvrir '{file}' en lecture: {error}" #: ../lib/Lire/Error.pm:87 #, perl-brace-format msgid "could not open '{file}' for writing: {error}" msgstr "impossible d'ouvrir '{file}' en écriture: {error}" #: ../lib/Lire/Error.pm:141 #, perl-brace-format msgid "directory '{directory}' already exists" msgstr "le répertoire '{directory}' existe déja" #: ../lib/Lire/LrCommand.pm:493 #, perl-brace-format msgid "error forking: {error}" msgstr "Une erreur est survenue lors du détachement du processur: {error}" #: ../lib/Lire/Error.pm:61 #, perl-brace-format msgid "file '{file}' is empty" msgstr "le fichier '{file}' est vide" #: ../lib/Lire/LrCommand.pm:508 #, perl-brace-format msgid "gzip exited with non zero status: {status}" msgstr "gzip a terminé avec un état d'erreur non-nul: {status}" #: ../lib/Lire/LrCommand.pm:486 msgid "gzip(1) isn't available" msgstr "gzip(1) n'est pas disponible" #: ../lib/Lire/Error.pm:96 #, perl-brace-format msgid "invalid option: '{option}'" msgstr "option invalide: '{option}'" #: ../lib/Lire/Error.pm:104 #, perl-brace-format msgid "invalid superservice: '{superservice}'" msgstr "superservice invalide: \"{superservice}\"" #: ../lib/Lire/Config/Scalar.pm:59 #, perl-brace-format msgid "invalid value for parameter '{parameter}': {value}" msgstr "valeur invalide pour le paramètre '{parameter}': {value}" #: ../lib/Lire/Error.pm:125 #, perl-brace-format msgid "missing '{argument}' argument" msgstr "argument '{argument}' manquant" #: ../lib/Lire/Error.pm:117 #, perl-brace-format msgid "missing '{command}' command" msgstr "la commande \"{command}\" est manquante" #: ../lib/Lire/OutputFormats/Excel95.pm:46 msgid "missing CPAN module Spreadsheet::WriteExcel" msgstr "le module CPAN Spreadsheet::WriteExcel est manquant" #: ../lib/Lire/Error.pm:114 #, perl-brace-format msgid "missing {make} '{command}' command" msgstr "la commande {make} \"{command}\" est manquante" #: ../lib/Lire/UI/BoolWidget.pm:27 msgid "no" msgstr "non" #: ../lib/Lire/LrCommand.pm:478 ../lib/Lire/LrCommand.pm:505 #, perl-brace-format msgid "read failed: {error}" msgstr "lecture erronée: {error}" #: ../script/lr_spec2pot.in:123 msgid "" "specs are strings of the form schema:, filter::, report:" ":, config_spec: or report_cfg:\n" msgstr "" "Les specs sont des chaînes de caractères ayant pour forme schema:, " "filter::, report::, config_spec: ou " "report_cfg:\n" #: ../lib/Lire/Error.pm:146 msgid "too many arguments" msgstr "trop d'arguments" #: ../lib/Lire/UI/BoolWidget.pm:27 msgid "yes" msgstr "oui" #: ../lib/Lire/LrCommand.pm:349 #, perl-brace-format msgid "{program} as shipped with Lire version {version}" msgstr "{program}, fourni avec Lire {version}" #. REFERENCE: lire.xml #: config-spec.pot.pl:278 msgid "À quelle fréquence désirez-vous générer ce rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:40 msgid "À quelle fréquencer importer le journal dans le store" msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:394 msgid "Étiquetter les points" msgstr "" #~ msgid "Areas" #~ msgstr "Aires" #~ msgid "Autoresponder disclaimer text" #~ msgstr "Texte d'avis de non-responsabilité du répondeur automatique" #~ msgid "Autoresponder explanation text" #~ msgstr "Texte d'explication du répondeur automatique" #~ msgid "Autoresponder input spool" #~ msgstr "File d'entrée du répondeur" #~ msgid "Autoresponder spool check interval" #~ msgstr "Intervale de vérification de la file d'entrée du répondeur" #, fuzzy #~ msgid "Bestandstype van het gegenereerde rapport" #~ msgstr "Type de fichier pour rapport généré" #~ msgid "Controls whether or not a bspline curve will be drawn over the plot." #~ msgstr "Défini sur une courbe B-spline sera tracée par dessus le diagramme." #~ msgid "Controls whether or not a regression line will be drawn." #~ msgstr "Spécifie si une ligne de régression sera dessinée ou non." #~ msgid "Controls whether or not the points will be labelled." #~ msgstr "Défini si les points seront étiquettés ou non." #, fuzzy #~ msgid "De superservice die gebruikt is in deze sectie." #~ msgstr "Les superservices couverts dans cette section." #~ msgid "Directories containing DLF converter initializers (obsolete)." #~ msgstr "" #~ "Les répertoires contenant des initialiseurs de convertisseurs DLF " #~ "(obsolète)." #~ msgid "Directories containing plugin initializers." #~ msgstr "Répertoires contenant les initialiseurs de plugins." #~ msgid "Directories containing report configuration templates." #~ msgstr "Répertoires contenant les gabarits de spécification de rapport." #~ msgid "Directories containing report specifications." #~ msgstr "Répertoires contenant les spécifications de rapports." #~ msgid "DlfStreams configuration" #~ msgstr "Configuration des streams DLF" #~ msgid "" #~ "During its operation Lire generates intermediate files that are normally " #~ "removed when done with. If you wish to study or debug the way Lire works " #~ "you can prevent Lire from deleting them with this option. The files will " #~ "be stored in the directory set in the `TMPDIR' " #~ "environment variable." #~ msgstr "" #~ "Pendant ses traitements, Lire génère des fichiers intermédiaires qu'il " #~ "efface lorsque plus nécessaires. Si vous voulez étudier ou déboguer le " #~ "fonctionnement de Lire, il vous est possible de l'empêcher de les effacer " #~ "en activant cette option. Les fichiers seront conservés dans le " #~ "répertoire indiqué dans la variable d'environnement \"TMPDIR\"." #~ msgid "" #~ "Each ImportJob can have its own import period. Monthly and yearly cron " #~ "jobs are run on the first day of the month or year. Weekly cron jobs are " #~ "run on monday morning 00:00." #~ msgstr "" #~ "Chaque Import Job peut avoir sa propre période d'importation. Les jobs " #~ "cron mensuels et annuels sont exécutés le premier jour du mois ou de " #~ "l'année tandis que les hebdomadaires le sont le lundi matin à minuit." #, fuzzy #~ msgid "Eerste Y variabele" #~ msgstr "Première variable en Y" #~ msgid "" #~ "Email address in the \"From\" field of report emailed by the responder." #~ msgstr "" #~ "L'adresse spécifiée dans le champ \"From\" des courriels contenant le " #~ "rapport envoyé par le répondeur." #~ msgid "Email address to send report from." #~ msgstr "Adresse de courriel à partir de laquelle envoyer le rapport." #~ msgid "" #~ "Email address where users of the responder should reply if different from " #~ "the value set for \"lr_mail_from\"." #~ msgstr "" #~ "L'adresse email à laquelle les utilisateurs du répondeur doivent " #~ "répondre, si différente de la valeur donnée à \"lr_mail_from\"." #~ msgid "Email addresses to mail report to." #~ msgstr "Adresse de courriel où envoyer le rapport." #~ msgid "Enable debugging output" #~ msgstr "Activer l'affichage d'information de débogage" #~ msgid "Encoding used in the formatted reports." #~ msgstr "Encodage utilisé dans les rapports formattés." #~ msgid "Encoding used in the log file." #~ msgstr "Encodage utilisé dans le fichier de journal." #~ msgid "Filter to apply to the log file." #~ msgstr "Filtre à appliquer au fichier de journal." #~ msgid "Font to use in charts" #~ msgstr "Police utilisée dans les diagrammes" #~ msgid "Generate the report on one page" #~ msgstr "Générer ce rapport sur une page unique" #~ msgid "How often to import the log into the store" #~ msgstr "À quelle fréquencer importer le journal dans le store" #~ msgid "How often you want to generate the report" #~ msgstr "À quelle fréquence désirez-vous générer ce rapport" #~ msgid "" #~ "If the `lr_archive' option is enabled, this is where " #~ "the requests will be archived." #~ msgstr "" #~ "Lorsque l'option \"lr_archive\" est active, le " #~ "répertoire où les requêtes seront archivées." #~ msgid "" #~ "If you select a numerical variable here, it will be used for the X axis " #~ "instead of the 'case_var' variable." #~ msgstr "" #~ "Si vous indiquez une variable numérique, elle sera utilisée pour l'axe " #~ "des X à la place de la variable \"case_var\"." #~ msgid "" #~ "If you want your report to be diplayed on one page, enable this option. " #~ "Otherwise a multiple page document will be generated." #~ msgstr "" #~ "Si vous désirez voir apparaître votre rapport sur une seule page, activez " #~ "cette option. Autrement un document à plusieurs pages sera généré." #~ msgid "" #~ "It is needed to identify the import jobs for Lire to process them " #~ "properly. Set this variable to do so." #~ msgstr "" #~ "Il est nécessaire d'identifier les import jobs afin que Lire puisse les " #~ "traiter correctement. Utilisez cette variable pour ce faire." #~ msgid "" #~ "It is needed to identify the report jobs for Lire to process them " #~ "properly. Set this variable to do so. NOTE: This name should contains " #~ "only alphanumeric characters, hyphens or underscores." #~ msgstr "" #~ "Il est necessaire d'identifier les report jobs afin que Lire puisse les " #~ "traiter correctement. Utilisez cette variable pour ce faire. NOTE: Cet " #~ "identifiant ne peut contenir que des caracteres alphanumeriques, des " #~ "tirets et des caracteres de soulignage." #~ msgid "" #~ "It is now possible to customize the presentation of some elements of the " #~ "HTML reports. The default's Lire CSS for HTML provides a good " #~ "presentation but this option gives you the ability to use your own " #~ "version." #~ msgstr "" #~ "Il est maintenant possible de personnaliser la présentation de certains " #~ "éléments des rapports HTML. La feuille de style par défaut de Lire pour " #~ "le HTML assure une présentation adéquate mais cette option vous donne la " #~ "possibilité d'utiliser votre propre feuille de style." #~ msgid "" #~ "It's generally a good idea to give programs only the minimum amount of " #~ "privileges required to run and restrict all else. Lire does not need to " #~ "run as root for normal operation and it's therefore recommended practice " #~ "to run it in a dedicated UNIX account. Lire checks its user ID when it " #~ "starts and aborts when it finds that it runs as root. You can disable " #~ "this check here so that Lire can be run from the superuser account. " #~ "Caveat emptor." #~ msgstr "" #~ "Il est de bon aloi de restreindre les privilèges alloués aux processus au " #~ "minimum. Lire ne requiert pas l'utilisation du compte \"root\" pour son " #~ "fonctionnement normal. Il est donc conseillé de créer un compte UNIX " #~ "dédié. Lire vérifie son id d'utilisateur à son démarrage et s'arrête s'il " #~ "détermine qu'il tourne sur le compte du superutilisateur. Cette option " #~ "vous permet de désactiver cette vérification à vos risques et périls." #~ msgid "Keep intermediate files" #~ msgstr "Garder les fichiers intermédiaires" #, fuzzy #~ msgid "Kort hoeveelheid bytes (Kb, Mb, ...) af" #~ msgstr "Abréger les décomptes en octets (Ko, Mo, ...)" #~ msgid "LaTeX Customization" #~ msgstr "Paramétrage de LaTeX" #~ msgid "Label points" #~ msgstr "Étiquetter les points" #, fuzzy #~ msgid "Lijst van secties voor het rapport." #~ msgstr "List des sections définies dans le rapport." #~ msgid "" #~ "Lire can either save its formatted report as a file on a filesystem or " #~ "send it by email to a chosen address. This option lets you configure this." #~ msgstr "" #~ "Lire peut sauvegarder ses rapports formattés dans un fichier sur le " #~ "disque ou bien l'envoyer par email à une adresse spécifiée. Cette option " #~ "vous permet de déterminer cela." #~ msgid "" #~ "Lire can format its reports in a variety of ways, from a simple plain " #~ "text file to a pretty PDF file suitable for printing." #~ msgstr "" #~ "Lire peut formatter ses rapports de différentes façons, du texte simple " #~ "au PDF, plus joli et plus approprié pour l'impression." #~ msgid "" #~ "Lire can output a lot of information while it runs. If Lire runs from a " #~ "batch environment such as an autoresponder or a cron job, it may be more " #~ "convenient to send this data to the system log so that it may be " #~ "inspected later." #~ msgstr "" #~ "Lire peut générer beaucoup d'information de sortie lors de son " #~ "fonctionnement. Si Lire fonctionne via un traitement automatisé comme le " #~ "répondeur ou une tâche cron, il peut être plus approprié d'envoyer ces " #~ "données dans le journal du système pour inspection ultérieure." #~ msgid "" #~ "Lire gathers data by \"superservices\", which in short are types of " #~ "\"services\". This option let you select the type of data that this " #~ "report job should process, whether it is database, web, email data or any " #~ "other type available in this list." #~ msgstr "" #~ "Lire assemble les données par \"superservices\", qui en gros sont des " #~ "types de services. Cette option vous permet de sélectionner le type de " #~ "données que ce report job devra traiter: web, base de données, email ou " #~ "n'importe quel type affiché dans cette liste." #~ msgid "" #~ "Makes Lire display byte counts in a legible format. Binary scales are " #~ "used, so `1 Kb' means `1024 bytes'." #~ msgstr "" #~ "Indique à Lire d'afficher les décomptes d'octets dans un format lisible. " #~ "Une échelonnage binaire est opéré, de sorte que \"1Kb\" ait pour valeur " #~ "\"1024 octets\"." #~ msgid "" #~ "Makes Lire display numbers in a legible format. Decimal scales are used, " #~ "so `1K' requests means `1000' requests." #~ msgstr "" #~ "Demande l'affichage des nombres dans un format lisible. Les unités sont " #~ "échelonnées sur une base décimale donc \"1K requêtes\" signifie \"1000 " #~ "requêtes\"." #~ msgid "" #~ "Makes Lire display times in a legible format, using `m', `h' and `d' " #~ "suffixes." #~ msgstr "" #~ "Demande l'affichage du temps dans un format lisible, en utilisant les " #~ "suffixes \"m\", \"h\" et \"d\"." #, fuzzy #~ msgid "Naam van de ReportJob." #~ msgstr "Nom du ReportJob." #~ msgid "Numerical X Variable" #~ msgstr "Variable numérique des X" #~ msgid "" #~ "Numerical variable for which the distribution will be plotted for the " #~ "cases selected by 'case_var'." #~ msgstr "" #~ "Une variable numérique pour laquelle la distribution sera tracée pour les " #~ "cas choisis pour \"case_var\"." #~ msgid "Path to the directory containing old style DLF converters." #~ msgstr "" #~ "Chemin d'accès au répertoire contenant les anciens convertisseurs DLF." #~ msgid "Path to the old address.cf file." #~ msgstr "Chemin d'accès à l'ancien fichier address.cf." #~ msgid "Path to the unicode.tex file" #~ msgstr "Chemin d'accès au fichier \"unicode.tex\"" #~ msgid "Plot numbers" #~ msgstr "Afficher les nombres" #~ msgid "Plot stacked areas instead of bars." #~ msgstr "Dessine des aires empilées à la place de barres." #~ msgid "Plot the y number above the bars?" #~ msgstr "Afficher le nombre en Y au-dessus des barres?" #~ msgid "Plot the y number beside the points?" #~ msgstr "Afficher les nombres en Y à côté des points?" #, fuzzy #~ msgid "Rapport Configuratie" #~ msgstr "Configuration de rapport" #~ msgid "Regression line" #~ msgstr "Ligne de régression" #~ msgid "Report Configuration" #~ msgstr "Configuration de rapport" #~ msgid "Report Generation Schedules" #~ msgstr "Horaires de génération des rapports" #~ msgid "" #~ "Report configuration files are text files with a specific syntax designed " #~ "to describe the type of information displayed in the report and the " #~ "presentation thereof. Lire provides a typical configuration file for each " #~ "superservice but you can also create your own, tailored to your needs." #~ msgstr "" #~ "Les fichiers de configuration de rapport sont des fichiers texte avec une " #~ "syntaxe particulière décrivant le type d'informations affichées dans le " #~ "rapport ainsi que sa présentation. Lire est fourni avec un fichier-type " #~ "de configuration pour chaque superservice mais vous pouvez créer le vôtre " #~ "accordé à vos besoins." #~ msgid "Report configuration." #~ msgstr "Configuration de rapport." #~ msgid "" #~ "ReportJob's must be generated on one or more periods, each of which have " #~ "to be described as a \"report schedule\". A report schedule let you " #~ "specify which report should be formatted, following which configuration " #~ "at which frequency." #~ msgstr "" #~ "Les ReportJobs doivent portent sur une ou plusieurs périodes, chacune " #~ "d'elles étant alors appelée \"planification de rapport\". Une " #~ "planification de rapport vous permet de spécifier quel rapport sera " #~ "formatté, sa configuration ainsi que sa fréquence de génération." #~ msgid "ReportJobs configured in the current store." #~ msgstr "ReportJobs configurés dans le store actuel." #, fuzzy #~ msgid "Sectiedefinitie" #~ msgstr "Définition de la section" #~ msgid "Select a fourth variable to plot." #~ msgstr "Choisissez une quatrième variable à tracer." #~ msgid "Select a fourth variable to stack." #~ msgstr "Choisissez la quatrième variable à empiler." #~ msgid "Select a second variable to plot." #~ msgstr "Choisissez une deuxième variable à tracer." #~ msgid "Select a second variable to stack." #~ msgstr "Choisissez la deuxième variable à empiler." #~ msgid "Select a third variable to plot." #~ msgstr "Choisissez une troisième variable à tracer." #~ msgid "Select a third variable to stack." #~ msgstr "Choisissez la troisième variable à empiler." #~ msgid "" #~ "Select the report configuration that should be used for this schedule." #~ msgstr "" #~ "Choisissez la configuration de rapport à utiliser pour cette " #~ "planification." #~ msgid "Select the variable which represents the X components of the points." #~ msgstr "" #~ "Choisissez la variable qui représentera les composants en X des points." #~ msgid "" #~ "Select the variable which represents the first component of the stack." #~ msgstr "" #~ "Choisissez la variable représentée par le premier élément de la pile." #~ msgid "Select the variable which represents the height of the first bar." #~ msgstr "" #~ "Choisissez la variable qui représente la hauteur de la première barre." #~ msgid "Send the formatted output via email." #~ msgstr "Envoyer le rapport formatté par email." #~ msgid "Sets the Reply-To email header" #~ msgstr "Valeur de l'en-tête de courriel \"Reply-To\"" #~ msgid "Should submissions be archived?" #~ msgstr "Les requêtes doivent-elles être archivées?" #~ msgid "" #~ "Some log files need preprocessing before they can be fed to the main Lire " #~ "engine. A common filter is zcat to decompress files " #~ "that were compressed using gzip or compress." #~ msgstr "" #~ "Certains fichiers de journaux requiert un traitement préalable avant de " #~ "passer au travers du moteur principale de Lire. La commande " #~ "zcat est un filtre typique utilisé pour décompresser " #~ "les fichiers compressés par gzip ou compress à la volée." #~ msgid "" #~ "Some log files, particularly those left by programs written by professor " #~ "D.J. Bernstein, use a timestamping format called tai64n which represents " #~ "points in time in nanosecond precision using the TAI timebase. This " #~ "program is required to do the conversion of TAI seconds to UTC seconds. " #~ "For more information, visit DJB's website. Specifying a full path is optional but " #~ "recommended. If you're not processing any log files using this format " #~ "(like qmail or djbdns), you don't have to touch this value: it is ignored " #~ "by Lire in this case." #~ msgstr "" #~ "Certains fichiers de journaux, en particulier ceux produits par les " #~ "programmes écrits par le professeur D. J. Bernstein, utilisent un format " #~ "d'horodatage appelé \"tai64n\" qui représente les points dans le temps " #~ "avec une précision à la nanoseconde selon la base de temps TAI. Ce " #~ "programme est requis pour faire la conversion des secondes TAI en " #~ "secondes UTC. Pour de plus amples informations, consultez le site web de DJB. La " #~ "spécification du chemin au complet est facultative mais recommandée. Si " #~ "vous ne traitez aucun fichier de journal en ce format (comme qmail ou " #~ "djbdns), cette option n'est pas tenue en compte." #~ msgid "" #~ "Some report output formats support the bundling of images (HTML, " #~ "PDF, ...). It is then possible to associate a logo with those reports, " #~ "such as the Lire logo (the default) or your company's, for example. This " #~ "parameter can either be an image file on your local filesystem or an URL." #~ msgstr "" #~ "Certains format de rapport (HTML, PDF, ...) supportent l'inclusion " #~ "d'images. Il est alors possible d'associer un logo à ces rapports, comme " #~ "par exemple le logo de Lire adjoint par défaut ou encore celui de votre " #~ "entreprise. Ce paramètre peut représenter un fichier sur votre système de " #~ "fichier local ou bien une URL." #~ msgid "" #~ "Some report output formats support the handling of hyperlinks (HTML, " #~ "PDF, ...). It is then possible to associate one with the logo to be " #~ "displayed in your report headers. By default, this link points to the " #~ "LogReport Foundation's website. If you don't want any link, set this " #~ "field to an empty value." #~ msgstr "" #~ "Certains formats de rapport supportent la gestion des hyperliens (HTML, " #~ "PDF, ...). Dans ce cas, il est possible d'en associer un au logo d'en-" #~ "tête. Par défaut, ce lien pointe vers le site web de la fondation " #~ "LogReport. Si vous ne désirez lui associer aucun hyperlien, laissez ce " #~ "champ vide." #~ msgid "" #~ "The Lire autoresponder modules extracts log file attachments from email " #~ "messages, processes the log files and e-mails the resulting report back " #~ "to the sender. When the responder is enabled, it will look in this " #~ "directory for incoming email messages. See the Lire User Manual for " #~ "information on configuring email delivery to this directory." #~ msgstr "" #~ "Les modules du répondeur automatique de Lire extraient les fichiers " #~ "journaux des courriels, traitent leur contenu et renvoient un courriel à " #~ "leur émetteur. Lorsque le répondeur est activé, il vérifie la présence de " #~ "courriels entrants dans ce répertoire. Consultez le manuel de " #~ "l'utilisateur de Lire pour savoir comment configurer la distribution des " #~ "courriels vers ce répertoire." #~ msgid "" #~ "The standard UNIX syslog daemon allows you to supply an identifier with " #~ "which each Lire-generated log line will be marked. It's recommended that " #~ "you use a short string without any spaces, for example `lire'." #~ msgstr "" #~ "Le service UNIX standard syslog permet d'indiquer un identifiant par " #~ "lequel chaque ligne générée par Lire sera marquée. On recommande " #~ "d'utiliser une chaîne de caractères courte et sans espace, comme par " #~ "exemple \"lire\"." #~ msgid "" #~ "The standard UNIX syslog daemon has a couple of ways to categorize log " #~ "messages. You can configure the syslog daemon to sort messages into " #~ "different log files based on the facility tag. See the syslog.conf(5) man " #~ "page for more information. You can select a syslog `facility' tag for " #~ "Lire to use here." #~ msgstr "" #~ "Le service UNIX standard syslog a plusieurs façon de catégoriser les " #~ "messages de journal. Vous pouvez configurer le service syslog pour trier " #~ "ces messages dans différents fichiers selon l'indicateur de facilité. " #~ "Cette option vous permet de sélectionner la facilité que Lire utilisera. " #~ "Consultez la page de manuel syslog.conf(5) pour plus d'information. " #~ msgid "" #~ "The subreport's numerical variable that will be used to compute the pie's " #~ "areas." #~ msgstr "" #~ "La variable numérique qui sera utilisée pour déterminer les aires du " #~ "diagramme." #~ msgid "The target type of the output report." #~ msgstr "Le type cible du rapport émis." #~ msgid "Third Y Variable" #~ msgstr "Troisième variable en Y" #~ msgid "" #~ "This file is appended to email messages that are sent back by the " #~ "autoresponder." #~ msgstr "" #~ "Ce fichier est ajouté aux courriels renvoyés par le répondeur automatique." #~ msgid "" #~ "This file is prepended to email messages that are sent back by the " #~ "autoresponder." #~ msgstr "" #~ "Ce fichier sera placé au début des courriels renvoyés par le répondeur " #~ "automatique." #~ msgid "" #~ "This is a file name template that may contain strftime(3) interpolation." #~ msgstr "" #~ "Ceci est un gabarit de nom de fichier pouvant contenir une interpolation " #~ "fournie par strftime(3)." #~ msgid "" #~ "This is the frequency by which this report schedule will be executed. The " #~ "value for this parameter can be either \"hourly\", \"daily\", \"weekly\", " #~ "\"monthly\" or \"yearly\". NOTE: to generate weekly, monthly or yearly " #~ "reports, you need to have at least one daily report schedule if you often " #~ "clean your DLF store. This is because Lire uses the merging algorithm " #~ "when it can't find the data in the DLF database and only daily reports " #~ "are considered in this case." #~ msgstr "" #~ "La fréquence à laquelle cette planification de rapport sera exécutée. La " #~ "valeur de ce paramètre peut être \"hourly\", \"daily\", \"weekly\", " #~ "\"monthly\" or \"yearly\" (\"horaire\", \"quotidien\", \"hebdomadaire\"," #~ "\"mensuel\" ou \"annuel\", respectivement). NOTE: pour générer des " #~ "rapports hebdomadaires, mensuels ou annuels, au moins une planification " #~ "de rapport quotidienne devra être disponible si vous nettoyer votre store " #~ "DLF. Ce, parce que lorsqu'il ne peut trouver les données dans la base de " #~ "donnée, Lire génère ces rapports par un algorithme de jonction dans " #~ "lequel seuls les rapports quotidiens sont considérés. " #~ msgid "" #~ "This let you configure the different attributes (currently only one) for " #~ "the generated file." #~ msgstr "" #~ "Cette option vous permet de configurer les différents attributs (un seul " #~ "est disponible pour l'instant) du fichier généré." #~ msgid "" #~ "This let you specify the subject that will appear in the generated " #~ "emails, as a way of identifying the received reports." #~ msgstr "" #~ "Ce paramètre pour permet d'indiquer le sujet qui apparaîtra dans les " #~ "courriels générés automatiquement afin d'identifier les rapports reçus." #~ msgid "" #~ "This option can be used to include LaTeX code that will be inserted in " #~ "LaTeX formatted reports (this also include the DVI, PS and PDF output " #~ "formats). This can be use to custommize headers or fonts." #~ msgstr "" #~ "Cette option peut être utilisée pour inclure du code LaTeX qui sera " #~ "inséré dans les rapports formattés (qui incluent ceux aux formats DVI, PS " #~ "et PDF). Ceci permet de personnaliser les en-têtes et les fontes." #~ msgid "" #~ "This parameter describes the service by which the specified logfile was " #~ "produced. This parameter is mandatory since Lire has no way of deducing " #~ "it otherwise." #~ msgstr "" #~ "Ce paramètre indique le service par lequel le fichier journal spécifié a " #~ "été produit. Ce paramètre est obligatoire puisque Lire ne peut le déduire " #~ "autrement." #~ msgid "" #~ "This plain text file is appended to email messages that are sent back by " #~ "the autoresponder." #~ msgstr "" #~ "Ce fichier en texte simple est ajouté aux courriels renvoyés par le " #~ "répondeur automatique." #~ msgid "" #~ "To generate PDF reports you need ps2pdf. This is part of the Ghostscript " #~ "distribution. See the User Manual for download locations." #~ msgstr "" #~ "La commande \"ps2pdf\" est nécessaire pour générer des rapports PDF. Elle " #~ "fait partie de la distribution de Ghostscript. Consultez le manuel de " #~ "l'utilisateur pour les adresses de téléchargement." #~ msgid "" #~ "To generate PostScript or PDF reports you need odvips which is the Omega " #~ "version of dvips. It is bundled with the TeTeX distribution since version " #~ "0.9. See the User Manual for download locations." #~ msgstr "" #~ "Pour générer des rapports en PostScript ou en PDF, vous devez avoir " #~ "\"odvips\", la version Omega de \"dvips\". Cette commande est fournie " #~ "avec la distribution TeTeX depuis sa version 0.9. Consultez le manuel de " #~ "l'utilisateur pour les informations de télécharment." #, fuzzy #~ msgid "Type van het logbestand." #~ msgstr "Type du journal." #~ msgid "UNIX syslog daemon" #~ msgstr "Le service UNIX syslog" #~ msgid "" #~ "Use this parameter in the case where you want your reports formatted in a " #~ "different encoding than the system's default." #~ msgstr "" #~ "Utilisez ce paramètre au cas où vous désirez formatter vos rapports dans " #~ "un encodage différent de celui utilisé par votre système." #~ msgid "" #~ "Use this parameter in the case where your log file is in a different " #~ "encoding than the system's default." #~ msgstr "" #~ "Utilisez ce paramètre au cas où vos fichiers journaux sont encodés dans " #~ "une format différent de votre système." #~ msgid "Values Variable" #~ msgstr "La variable des valeurs" #, fuzzy #~ msgid "Vierde Y Variabele" #~ msgstr "Troisième variable en Y" #~ msgid "" #~ "When reports are scheduled, they can be output in different forms and " #~ "different formats. This is what OutputJobs are about and you can " #~ "configure several of them for the same schedule." #~ msgstr "" #~ "Les OutputJobs permettent la génération de rapports sous diverses formes " #~ "et en plusieurs formats. Plusieurs peuvent être programmés pour la même " #~ "période." #~ msgid "" #~ "When the responder is enabled, it will often check the spool directory " #~ "for incoming email messages. You can enter the frequency in minutes here." #~ msgstr "" #~ "Lorsque le répondeur est activé, il vérifie souvent la présence de " #~ "courriels dans la file d'entrée. Vous pouvez spécifier la fréquence de " #~ "vérification ici, en minutes." #~ msgid "" #~ "When this parameter is set, the Responder will save each submitted " #~ "message to the directory specified in the 'lr_archive_dir' parameter." #~ msgstr "" #~ "Lorsque ce paramètre est activé, le répondeur gardera une copie de chaque " #~ "message reçu dans le répertoire spécifié dans la paramètre " #~ "\"lr_archive_dir\"." #~ msgid "Which CSS stylesheet should be used for your HTML reports ?" #~ msgstr "" #~ "Quelle feuille de style CSS doit être utilisée pour vos rapports en HTML ?" #~ msgid "" #~ "Which URI should be pointed to by the logo displayed in your report " #~ "headers?" #~ msgstr "" #~ "Quelle URI devrait être pointée par le logo affiché dans vos en-têtes de " #~ "rapports." #~ msgid "Which logo to display in the report headers?" #~ msgstr "Quel logo afficher dans l'en-tête des rapports?" #~ msgid "Which syslog `facility' to use" #~ msgstr "Choix de la facilité \"syslog\" à utiliser" #~ msgid "Which syslog program identifier to use" #~ msgstr "Identifiant à utiliser pour le programme \"syslog\"" #~ msgid "" #~ "With \"W\", week numbers range from 00 to 53, starting with the first " #~ "Monday as the first day of week 01; with \"U\", week numbers range from " #~ "00 to 53, starting with the first Sunday as the first day of week 01 and " #~ "with \"ISO\", week numbers are computed according to ISO 8601:1988, range " #~ "01 to 53, where week 1 is the first week that has at least 4 days in the " #~ "current year, and with Monday as the first day of the week." #~ msgstr "" #~ "Avec \"W\", les semaines sont numérotées de 00 à 53 en prenant comme " #~ "point de départ le premier lundi de la semaine 01. Avec \"U\", les " #~ "semaines sont numérotées de la même façon en tenant compte du dimanche " #~ "comme premier jour de la semaine; tandis qu'avec \"ISO\", les semaines " #~ "sont calculées selon le standard ISO 8601:1988, de 01 à 53, avec comme " #~ "semaine 01 celle qui contient au moins 4 jours dans l'année courante en " #~ "prenant lundi comme premier jour." #~ msgid "X component" #~ msgstr "Composant des X" #~ msgid "Y component" #~ msgstr "Composant des Y" lire-2.1.1/all/po/nl.mo0000644000175000017500000003263711677606225011552 00000000000000  q.y  2**(1+E ZhlA$%JSek(z #  , 3 >LQV!\$~    , 8CSeVv    5'Jr .,# P Z3e#  &+4 JVr+=O_p '/( V4V   & )AJ7 ,,&Bi*&28V+r"DW0[!"&""""# )#6#=#;##$4.$c$.U%% %%%>% &&0&M&l&"s&&&&&'&&' '&'/*' Z' d'''' ' ''' '%')(&1(X(_( q((5((( (( )),))) ))* *)"*#L*p**"*****4* 0+:+0B+ s+ +8+ +3+, ,,:,I, e,o,x, ,,,,, -#- =-G-a-q----- -- -/.5. =./K.2{.b.J/\/|/// y00 00"0C0';19c22 2=2B2A3^31w333(36 4 A4b4/4&444^5q5*t5D'+t9Zj*osn^(Q:1dfq m 4`Oh-p.H{>&[?ML7%Bc\aF}6gEzGxkrK"~Xiw_!3|P/R N@UV;W2$leb,SYu8CIAT ]<0)=#Jy5v Lire {version} - the versatile log-analyser http://www.logreport.org/ Lire is developed and maintained by the LogReport Development Team Copyright (c) 2000-2004 Stichting Logreport Foundation Some parts of Lire are also copyrighted by third-parties. Please consult the AUTHORS file in the Lire distribution for the complete list. (X)HTML-- This option does not have any attributes ---- empty list ---- no date ---- no stream ---- unidentified --< Cancel >< OK >A report output can be emailed to many addresses at the same time. Fill in this list with those. At least one address is required.A text file that will be included with the report.A title that will appear along the Y axis.A title that will appear under the X axis.A title that will appears in the report.A typecode that can be error for line which resulted in an error, continuation for lines marked for processing at a later time and ignored for lines that were ignored. Abbreviate time units (minutes, hours, ...)About Lire {version}About Lire...AddAn error occured: {error}Applied filter in this section: Filters applied in this section:ApplyAvailable DLF converters:Available output formats:Available report templates:BrowseCannot create directory {directory}.Caution:Choose a Store...CloseCommon optionsConfiguration for the {schema} DlfStreamCopyCreate a New Store...DLF StreamsDVIDays of DLF to keepDeleteDirectories containing DLF schemas.Distribution chartDlf CreatedDlf IDDlf SourceDocbook PathsDownEditEnds:Error creating store: {error}Error loading spec '{spec}': {error}Error opening store: {error}ErrorsExcel95 SpreadsheetFirst SectionFourth Y VariableHow are week numbers computed?Ignored LinesImport JobsImportant:Invalid commandInvalid directoryInvalid filenameInvalid period '{period}'. Should be one of hourly, daily, weekly, monthly or yearly. LaTeXLast SectionLine NumberLire PathsLire PreferencesLire ReportList of filters that will be applied to this section.List of sections defined in the report.Location of the archiveMerging optionsMissing '{argument}' argument. New...NextNext PageNo help available.No subreports were generated for this section.ObsoleteOpen...Path to the log file that will be processed.Pie chartPlain TextPlot one to four variable as lines against another.Preferences...Prevent Lire from being run as rootPreviousPrevious PagePrint Lire version and exit.Program PathsProperties for {plugin}QuitRecords:Report ConfigurationsReport JobsReport generated on: {date}Report generated {date}Report generation optionsReport's sectionsReport's titleReporting on period: {period}ReportsResponder PreferencesSection definitionSection's SuperserviceSection's contentSection's filtersSection's titleSelect a CommandSelect a DirectorySelect a FileStarts:Store the formatted output into a file.Store: Table Of ContentsThe superservices that is used by this section.The title that will appear on the chart.This field contains an identifier relating the record to the process that created it. This field contains an integer which uniquely identify this DLF record in the stream. This report is missing: {reason}TimestampTip:To generate DVI, PostScript or PDF reports you need Lambda which is the Omega version of LaTeX. It is bundled with the TeTeX distribution since version 0.9. See the User Manual for download locations.Total for {nrecords} recordsUnknown PeriodUnknown command: '{command}'. UpUsage: lr_cron Usage: lr_report_cfg2xml XHTML is the modern form of HTML. XHTML files are actually XML files with an HTML vocabulary. Since XHTML 1.0 is just a little bit more than HTML 4.01, the result displayed will not change considerably but certain people like to live on the bleeding edge...You need to use the --template option to merge reports.Your {format} report.[Configure]could not open '{file}' for reading: {error}could not open '{file}' for writing: {error}directory '{directory}' already existsfile '{file}' is emptygzip exited with non zero status: {status}gzip(1) isn't availableinvalid option: '{option}'invalid superservice: '{superservice}'invalid value for parameter '{parameter}': {value}missing '{argument}' argumentmissing '{command}' commandmissing CPAN module Spreadsheet::WriteExcelmissing {make} '{command}' commandnospecs are strings of the form schema:, filter::, report::, config_spec: or report_cfg: too many argumentsyes{program} as shipped with Lire version {version}Project-Id-Version: Lire 1.5 Report-Msgid-Bugs-To: bugs@logreport.org POT-Creation-Date: 2011-12-31 14:22+0100 PO-Revision-Date: 2004-09-02 10:51+0200 Last-Translator: Joost van Baal Language-Team: LogReport Language: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n > 1; Lire {version} - de generieke logverwerker http://www.logreport.org/ Lire is geschreven en wordt onderhouden door het LogReport Ontwikkelaars Team Copyright (c) 2000-2004 Stichting Logreport Foundation Het auteursrecht op sommige onderdelen van Lire berust bij derden. Raadpleeg het AUTHORS bestand in het Lire pakket voor de volledige lijst. (X)HTML-- Deze optie heeft geen attributen ---- lege lijst ---- geen datum ---- geen stream ---- ongeidentificeerd --< Afbreken >< OK >Een rapport kan per email verzonden worden naar meerdere adressen.Vul deze lijst met die adressen. Minstens één adres is nodig.Een tekstbestand dat zal worden weergegeven in het rapport.Een titel naast de Y-as.Een titel onder de X-as.Een titel die zal worden weergegeven in het rapport.Een typecode. Deze is error voor regels die tot een fout leidden; continuation voor regels de gemarkeerd zijn voor latere verwerking; en ignored voor regels die genegeerd zijn. Kort tijdsaanduidingen (minuten, uren, ...) afOver Lire {version}Over Lire...Voeg toeEr trad een fout op: {error}Actieve filter in deze sectie:Actieve filters in deze sectie:ToepassenBeschikbare DLF converters:Beschikbare output formaten:Beschikbare rapport sjablonen:BladerKan map {directory} niet aanmaken.Pas op:Kies een Store...SluitGemeenschappelijke optiesConfiguratie voor de {schema} DlfStreamCopiëerMaak een Nieuwe Store...DLF StreamsDVIVoor hoeveel dagen moet de DLF bewaard blijven?VerwijderMappen die DLF schemas bevatten.Distributie diagramDlf AangemaaktDlf IDDlf SourceDocbookpadenOmlaagWijzigEindigt op:Fout bij maken van store: {error}Fout bij laden van spec '{spec}': {error}Fout bij openen van store: {error}FoutenExcel 95 WerkbladEerste SectieVierde Y VariabeleVolgens welke methode worden weeknummers vastgesteld?Genegeerde RegelsImporteer JobsBelangrijk:Ongeldig commandoOngeldige mapOngeldige bestandsnaamOngeldige periode '{period}'. Gebruik één van "hourly", "daily", "weekly", "monthly" of "yearly", voor uurlijks, dagelijks, wekelijks, maandelijks en jaarlijks. LaTeXLaatste SectieRegelnummerLire BestandspadenLire VoorkeurenLire RapportLijst van actieve filters in deze sectie.Lijst van secties voor het rapport.Plaats van het archiefOpties voor samenvoegenOntbrekend '{argument}' argument. Nieuw...VolgendeVolgende PaginaGeen hulp beschikbaar.Voor deze sectie zijn geen subrapporten gegenereerd.VerouderdOpen...Pad naar het logbestand dat verwerkt zal worden.TaartdiagramPlatte tekstPlot één tot vier variabelen als grafieken van elkaar.Voorkeuren...Zorg ervoor dat Lire niet als root uitgevoerd wordtVorigeVorige PaginaDruk Lire versie af en stop.ProgrammapadenEigenschappen voor {plugin}AfsluitenRecords:Rapport ConfiguratieRapport JobsRapport gegenereerd op: {date}Rapport gegenereerd op {date}Opties voor rapport generatieSecties van het rapportTitel van het rapportBetreft periode: {period}RapportenVoorkeuren voor ResponderSectiedefinitieSuperservice van de SectieInhoud van de sectieFilters van de SectieTitel van de SectieKies een CommandoKies een MapKies een bestandStart op:Bewaar de geformateerde uitvoer in een bestand.Store: InhoudsopgaveDe superservice die gebruikt is in deze sectie.De titel die zal worden weergegeven op de grafiek.Dit veld bevat een sleutel die het record relateert aan het process dat het record gemaakt heeft. Dit veld bevat een integer die dit DLF record in de stream identificeert. Dit rapport ontbreekt: {reason}TijdstipTip:Om DVI, Postscript of PDF rapporten te genereren, heeft u Lambda nodig. Dat is de Omega versie van LaTeX, en wordt geleverd met de TeTeX distributie sinds versie 0.9. In de Gebruikers Handleiding kunt u vinden waar u dit kunt downloaden.Totaal voor {nrecords} record(s)Onbekende PeriodeOnbekend commando: '{command}'. OmhoogGebruik: lr_cron Gebruik: lr_report_cfg2xml XHTML is de moderne vorm van HTML. XHTML bestanden zijn in feite XML bestanden met een HTML vocabulair. Omdat XHTML 1.0 slechts een klein beetje meer bevat dan HTML 4.01 zal het resultaat dat getoond wordt nauwelijks merkbaar anders zijn. Sommigen gebruiken echter liefst het allernieuwste...Gebruik de --template optie om rapporten samen te voegen.Uw {format} rapport.[Configureer]bestand '{file}' kon niet geopend worden om te lezen: {error}bestand '{file}' kon niet geopende worden om te schrijven: {error}map '{directory}' bestaat albestand '{file}' is leeggzip is gestopt met een niet-nul status: {status}gzip(1) is niet beschikbaarongeldige optie: '{option}'ongeldige superservice: '{superservice}'ongeldige waarde voor parameter '{parameter}': {value}ontbrekend argument '{argument}'ontbrekend commando '{command}'ontbrekende CPAN module Spreadsheet::WriteExcelontbrekend {make} '{command}' commandoneespecs zijn strings van de vorm schema:, filter::, report::, config_spec: or report_cfg: te veel argumentenja{program}, als geleverd met Lire {version}lire-2.1.1/all/po/nl.po0000644000175000017500000021562011677606225011550 00000000000000# This file holds the Dutch translations of Lire strings. # Copyright (C) 2004 Stichting LogReport Foundation # This file is distributed under the same license as the Lire package. # Joost van Baal , 2004. # # See also http://logreport.com/nl/ for some nice Dutch translations of # typical Lire-ese. # # $Id: nl.po,v 1.16 2009/01/17 11:59:47 vanbaal Exp $ # msgid "" msgstr "" "Project-Id-Version: Lire 1.5\n" "Report-Msgid-Bugs-To: bugs@logreport.org\n" "POT-Creation-Date: 2011-12-31 14:22+0100\n" "PO-Revision-Date: 2004-09-02 10:51+0200\n" "Last-Translator: Joost van Baal \n" "Language-Team: LogReport \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" #: ../lib/Lire/UI.pm:130 #, fuzzy msgid "" "\n" " Welcome to Lire, the versatile log-analyser!\n" "\n" " This is a quick graphical user-interface for configuring Lire and for\n" " managing DLF stores (the directories where your reports and logs data is\n" " stored and handled).\n" "\n" " To access the menubar, press or . To wander between\n" " the different widgets contained in a window or a dialog, use the\n" " key. When done, press or , choose the Lire\n" " widget and choose quit. Your changes will be savely stored.\n" "\n" " The first time you use Lire, you are encouraged to have a look at and to\n" " modify the global Lire preferences to ensure they suit your needs.\n" " Go to the \"Lire->Preferences...\" menu to do so.\n" "\n" " If you want to generate periodical reports, you should create a\n" " new DLF store and then add it import jobs and report jobs.\n" " Import jobs are meant to parse and convert specified logfiles into the\n" " store database for further processing, while report jobs process the\n" " gathered data to produce and format reports. Be sure you have some\n" " lr_cron calls in your personal crontab.\n" "\n" " If you think you could gain significant storage room after a while,\n" " you can also clear old records since Lire will still be able to produce\n" " periodical reports by merging previous daily reports.\n" msgstr "" "\n" " Dit is Lire, de generieke logverwerker. Welkom!\n" "\n" " Dit is een grafisch programma waarmee Lire geconfigureerd kan worden\n" " en waarmee met DLF Stores gewerkt kan worden. DLF Stores zijn de\n" " mappen waar rapporten en log gegevens zijn opgeslagen.\n" "\n" " Kies om het menu te activeren. Kies om de verschillende\n" " knoppen te activeren. Wanneer u klaar bent, kies dan , kies de\n" " Lire knop en kies Afsluiten. Uw wijzigingen zullen veilig opgeslagen\n" " zijn.\n" "\n" " Als dit de eerste keer is dat u Lire gebruikt, vergeet dan niet te\n" " kijken naar de globale Lire voorkeuren: vergewis uzelf ervan dat\n" " die naar uw smaak zijn. Gebruik hiervoor het \"Lire -> Voorkeuren...\"\n" " menu.\n" "\n" " Als u periodiek rapporten wilt laten genereren, dan zult u een nieuwe\n" " DLF Store moeten aanmaken. Daarna zult u daar import jobs en report\n" " jobs aan moeten toevoegen. Import jobs lezen en converteren specifieke\n" " log bestanden, en slaan het resultaat op in de DLF Store. Report jobs\n" " verwerken de verzamelde data tot geformatteerde rapporten. Zorg ervoor\n" " dat u lr_cron invokaties in uw persoonlijke crontab heeft staan.\n" "\n" " Om schijfruimte te besparen kunt u eventueel oude data omruimen; Lire\n" " kan immers periodieke rapporten genereren door de gegevens uit dagelijkse\n" " rapporten te combineren.\n" #: ../lib/Lire/UI.pm:267 #, perl-brace-format msgid "" " Lire {version} - the versatile log-analyser\n" "\n" " http://www.logreport.org/\n" "\n" " Lire is developed and maintained by the\n" " LogReport Development Team \n" "\n" "Copyright (c) 2000-2004 Stichting Logreport Foundation\n" "Some parts of Lire are also copyrighted by third-parties.\n" "Please consult the AUTHORS file in the Lire distribution\n" "for the complete list.\n" msgstr "" " Lire {version} - de generieke logverwerker\n" "\n" " http://www.logreport.org/\n" "\n" " Lire is geschreven en wordt onderhouden door het\n" " LogReport Ontwikkelaars Team \n" "\n" "Copyright (c) 2000-2004 Stichting Logreport Foundation\n" "Het auteursrecht op sommige onderdelen van Lire berust bij\n" "derden. Raadpleeg het AUTHORS bestand in het Lire pakket\n" "voor de volledige lijst.\n" #: ../lib/Lire/OutputFormats/HTML.pm:37 msgid "(X)HTML" msgstr "(X)HTML" #: ../lib/Lire/UI/CompoundWidget.pm:49 msgid "-- This option does not have any attributes --" msgstr "-- Deze optie heeft geen attributen --" #: ../lib/Lire/UI/ListWidget.pm:228 ../lib/Lire/UI/PluginWidget.pm:38 msgid "-- empty list --" msgstr "-- lege lijst --" #: ../lib/Lire/UI/StoreWindow.pm:406 msgid "-- no date --" msgstr "-- geen datum --" #: ../lib/Lire/UI/StoreWindow.pm:302 msgid "-- no stream --" msgstr "-- geen stream --" #: ../lib/Lire/Config/Dictionary.pm:61 msgid "-- unidentified --" msgstr "-- ongeidentificeerd --" #: ../lib/Lire/UI/Prefs.pm:121 ../lib/Lire/UI/StoreWindow.pm:210 #: ../lib/Lire/UI/StoreWindow.pm:254 ../lib/Lire/UI.pm:103 msgid "< Cancel >" msgstr "< Afbreken >" #: ../lib/Lire/UI/Prefs.pm:123 ../lib/Lire/UI/StoreWindow.pm:214 #: ../lib/Lire/UI/StoreWindow.pm:256 ../lib/Lire/UI.pm:105 msgid "< OK >" msgstr "< OK >" #. REFERENCE: lire.xml #: config-spec.pot.pl:242 #, fuzzy msgid "" "A list of directories which contain initialization scripts. These are short " "perl script that should register plugins with the Lire::PluginManager." msgstr "" "Een lijst van mappen met initializatie scripts. Dit zijn kleine Perl " "scripts die plugins registreren met Lire::PluginManager." #. REFERENCE: lire.xml #: config-spec.pot.pl:4 msgid "" "A report output can be emailed to many addresses at the same time. Fill in " "this list with those. At least one address is required." msgstr "" "Een rapport kan per email verzonden worden naar meerdere adressen.Vul deze " "lijst met die adressen. Minstens één adres is nodig." #: ../lib/Lire/LrCommand.pm:219 msgid "A text file that will be included with the report." msgstr "Een tekstbestand dat zal worden weergegeven in het rapport." #: ../lib/Lire/Config/ChartSpec.pm:59 msgid "A title that will appear along the Y axis." msgstr "Een titel naast de Y-as." #: ../lib/Lire/Config/ChartSpec.pm:54 msgid "A title that will appear under the X axis." msgstr "Een titel onder de X-as." #: ../lib/Lire/Config/ReportSpec.pm:40 msgid "A title that will appears in the report." msgstr "Een titel die zal worden weergegeven in het rapport." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:510 msgid "" "A typecode that can be error for line which resulted in " "an error, continuation for lines marked for processing " "at a later time and ignored for lines that were " "ignored. " msgstr "" "Een typecode. Deze is error voor regels die tot een " "fout leidden; continuation voor regels de gemarkeerd " "zijn voor latere verwerking; en ignored voor regels die " "genegeerd zijn. " #. REFERENCE: lire.xml #: config-spec.pot.pl:182 #, fuzzy msgid "Abbreviate byte counts (Kb, Mb, ...)" msgstr "Kort tijdsaanduidingen (minuten, uren, ...) af" #. REFERENCE: lire.xml #: config-spec.pot.pl:186 #, fuzzy msgid "Abbreviate numbers (Kb, Mb, ...)" msgstr "Kort cijfers af (Kb, Mb, ...)" #. REFERENCE: lire.xml #: config-spec.pot.pl:190 msgid "Abbreviate time units (minutes, hours, ...)" msgstr "Kort tijdsaanduidingen (minuten, uren, ...) af" #: ../lib/Lire/UI.pm:264 #, perl-brace-format msgid "About Lire {version}" msgstr "Over Lire {version}" #: ../lib/Lire/UI.pm:167 msgid "About Lire..." msgstr "Over Lire..." #. REFERENCE: lire.xml #: config-spec.pot.pl:92 msgid "Activer l'affichage d'information de débogage" msgstr "" #: ../lib/Lire/UI/ListWidget.pm:114 ../lib/Lire/UI/ListWidget.pm:139 msgid "Add" msgstr "Voeg toe" #. REFERENCE: lire.xml #: config-spec.pot.pl:2 msgid "Adresse de courriel où envoyer le rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:152 msgid "Adresse de courriel à partir de laquelle envoyer le rapport." msgstr "" #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:428 msgid "Afficher le nombre en Y au-dessus des barres?" msgstr "" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:362 config-spec.pot.pl:426 msgid "Afficher les nombres" msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:364 msgid "Afficher les nombres en Y à côté des points?" msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:406 msgid "Aires" msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:158 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:236 #, fuzzy, perl-brace-format msgid "An error occured while generating the chart: {error}" msgstr "Er trad een fout op: {error}" #: ../lib/Lire/Error.pm:53 #, perl-brace-format msgid "An error occured: {error}" msgstr "Er trad een fout op: {error}" #. REFERENCE: lire.xml #: config-spec.pot.pl:276 #, fuzzy msgid "An identifier for this output job." msgstr "Een identificeringscode voor deze output job." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:522 msgid "An optional message logged by the converter." msgstr "" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:75 #, perl-brace-format msgid "Analyser to use for {schema} schema" msgstr "" #: ../lib/Lire/ReportSection.pm:208 msgid "Applied filter in this section: " msgid_plural "Filters applied in this section:" msgstr[0] "Actieve filter in deze sectie:" msgstr[1] "Actieve filters in deze sectie:" #: ../lib/Lire/UI/ScalarListWidget.pm:43 ../lib/Lire/UI/ScalarListWidget.pm:72 msgid "Apply" msgstr "Toepassen" #: ../lib/Lire/LrCommand.pm:419 msgid "Available DLF converters:" msgstr "Beschikbare DLF converters:" #: ../lib/Lire/LrCommand.pm:432 msgid "Available output formats:" msgstr "Beschikbare output formaten:" #: ../lib/Lire/LrCommand.pm:408 msgid "Available report templates:" msgstr "Beschikbare rapport sjablonen:" #. REFERENCE: lire.xml #: config-spec.pot.pl:222 msgid "" "Avec \"W\", les semaines sont numérotées de 00 à 53 en prenant comme point " "de départ le premier lundi de la semaine 01. Avec \"U\", les semaines sont " "numérotées de la même façon en tenant compte du dimanche comme premier jour " "de la semaine; tandis qu'avec \"ISO\", les semaines sont calculées selon le " "standard ISO 8601:1988, de 01 à 53, avec comme semaine 01 celle qui contient " "au moins 4 jours dans l'année courante en prenant lundi comme premier jour." msgstr "" #: ../lib/Lire/LrCommand.pm:231 msgid "Backward compatibility." msgstr "" #: ../lib/Lire/UI/FileWidget.pm:38 msgid "Browse" msgstr "Blader" #. REFERENCE: lire.xml #: config-spec.pot.pl:128 msgid "Canal de sortie des erreurs (terminal ou redirection vers un fichier)" msgstr "" #: ../lib/Lire/LrCommand.pm:81 #, perl-brace-format msgid "Cannot create directory {directory}." msgstr "Kan map {directory} niet aanmaken." #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:450 msgid "Caution:" msgstr "Pas op:" #. REFERENCE: lire.xml #: config-spec.pot.pl:162 msgid "" "Ce fichier en texte simple est ajouté aux courriels renvoyés par le " "répondeur automatique." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:146 msgid "" "Ce fichier est ajouté aux courriels renvoyés par le répondeur automatique." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:150 msgid "" "Ce fichier sera placé au début des courriels renvoyés par le répondeur " "automatique." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:46 msgid "" "Ce paramètre indique le service par lequel le fichier journal spécifié a été " "produit. Ce paramètre est obligatoire puisque Lire ne peut le déduire " "autrement." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:8 msgid "" "Ce paramètre pour permet d'indiquer le sujet qui apparaîtra dans les " "courriels générés automatiquement afin d'identifier les rapports reçus." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:16 msgid "" "Ceci est un gabarit de nom de fichier pouvant contenir une interpolation " "fournie par strftime(3)." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:34 msgid "" "Ceci représente le chemin d'accès au fichier journal qui doit être importé. " "Ce chemin d'accès peut correspondre à un gabarit formatté selon la " "spécification de strftime(3). Par exemple, /var/log/apache/corp.com" "%Y%m%d.log.gz sera remplacé par quelque chose semblable à " "/var/log/apache/corp.com20040124.log.gz." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:26 msgid "" "Certains fichiers de journaux requiert un traitement préalable avant de " "passer au travers du moteur principale de Lire. La commande zcat est un filtre typique utilisé pour décompresser les fichiers " "compressés par gzip ou compress à la " "volée." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:342 msgid "" "Certains fichiers de journaux, en particulier ceux produits par les " "programmes écrits par le professeur D. J. Bernstein, utilisent un format " "d'horodatage appelé \"tai64n\" qui représente les points dans le temps avec " "une précision à la nanoseconde selon la base de temps TAI. Ce programme est " "requis pour faire la conversion des secondes TAI en secondes UTC. Pour de " "plus amples informations, consultez le site web de DJB. La spécification du chemin au " "complet est facultative mais recommandée. Si vous ne traitez aucun fichier " "de journal en ce format (comme qmail ou djbdns), cette option n'est pas " "tenue en compte." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:138 msgid "" "Certains format de rapport (HTML, PDF, ...) supportent l'inclusion d'images. " "Il est alors possible d'associer un logo à ces rapports, comme par exemple " "le logo de Lire adjoint par défaut ou encore celui de votre entreprise. Ce " "paramètre peut représenter un fichier sur votre système de fichier local ou " "bien une URL." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:142 msgid "" "Certains formats de rapport supportent la gestion des hyperliens (HTML, " "PDF, ...). Dans ce cas, il est possible d'en associer un au logo d'en-tête. " "Par défaut, ce lien pointe vers le site web de la fondation LogReport. Si " "vous ne désirez lui associer aucun hyperlien, laissez ce champ vide." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:304 msgid "" "Cet identifiant peut être utilisé comme référence à la configuration de ce " "rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:338 msgid "" "Cette liste de configuration contient la configuration pour chaque stream " "DLF du store." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:118 msgid "" "Cette option peut être utilisée pour inclure du code LaTeX qui sera inséré " "dans les rapports formattés (qui incluent ceux aux formats DVI, PS et PDF). " "Ceci permet de personnaliser les en-têtes et les fontes." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:12 msgid "" "Cette option vous permet de configurer les différents attributs (un seul est " "disponible pour l'instant) du fichier généré." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:42 msgid "" "Chaque Import Job peut avoir sa propre période d'importation. Les jobs cron " "mensuels et annuels sont exécutés le premier jour du mois ou de l'année " "tandis que les hebdomadaires le sont le lundi matin à minuit." msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:169 msgid "Chart" msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:164 msgid "Charts" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:346 msgid "Chemin d'accès au fichier \"unicode.tex\"" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:170 msgid "Chemin d'accès au répertoire contenant les anciens convertisseurs DLF." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:168 msgid "Chemin d'accès à l'ancien fichier address.cf." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:288 msgid "" "Choisissez la configuration de rapport à utiliser pour cette planification." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:416 msgid "Choisissez la deuxième variable à empiler." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:424 msgid "Choisissez la quatrième variable à empiler." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:420 msgid "Choisissez la troisième variable à empiler." msgstr "" #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:432 msgid "Choisissez la variable qui représente la hauteur de la première barre." msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:400 msgid "Choisissez la variable qui représentera les composants en X des points." msgstr "" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:372 config-spec.pot.pl:404 msgid "" "Choisissez la variable qui sera représentée par la composante Y des points." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:412 msgid "Choisissez la variable représentée par le premier élément de la pile." msgstr "" #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:436 msgid "" "Choisissez optionnellement une variable qui représente la hauteur de la " "seconde barre." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:376 msgid "Choisissez une deuxième variable à tracer." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:384 msgid "Choisissez une quatrième variable à tracer." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:380 msgid "Choisissez une troisième variable à tracer." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:120 msgid "Choix de la facilité \"syslog\" à utiliser" msgstr "" #: ../lib/Lire/UI.pm:333 msgid "Choose a Store..." msgstr "Kies een Store..." #: ../lib/Lire/UI/StoreWindow.pm:193 #, perl-brace-format msgid "Cleaning stream '{stream}'" msgstr "" #: ../lib/Lire/UI.pm:193 msgid "Close" msgstr "Sluit" #: ../lib/Lire/LrCommand.pm:188 msgid "Common options" msgstr "Gemeenschappelijke opties" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:398 msgid "Composant des X" msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:402 msgid "Composant des Y" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:298 msgid "Configuration de rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:286 msgid "Configuration de rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:336 #, fuzzy msgid "Configuration des streams DLF" msgstr "Configuratie voor de {schema} DlfStream" #: ../lib/Lire/Config/DlfStreamSpec.pm:63 #, perl-brace-format msgid "Configuration for the {schema} DlfStream" msgstr "Configuratie voor de {schema} DlfStream" #. REFERENCE: lire.xml #: config-spec.pot.pl:294 #, fuzzy msgid "Configurations de rapport" msgstr "Rapport Configuratie" #: ../lib/Lire/UI/StoreWindow.pm:241 #, perl-brace-format msgid "Configuring stream '{stream}'" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:318 msgid "Contenu de la section" msgstr "" #: ../script/lr_log2report.in:19 msgid "" "Converts using and generate a report in " "." msgstr "" #: ../script/lr_log2mail.in:24 msgid "" "Converts a log file using and email it to the recipients " "specified. The log file is read from STDIN unless the --log-file option is " "used." msgstr "" #: ../lib/Lire/UI/ListWidget.pm:115 ../lib/Lire/UI/ListWidget.pm:141 msgid "Copy" msgstr "Copiëer" #: ../lib/Lire/UI.pm:302 msgid "Create a New Store..." msgstr "Maak een Nieuwe Store..." #: ../lib/Lire/LrCommand.pm:83 #, fuzzy, perl-brace-format msgid "Created {directory}." msgstr "Maakte {directory}." #: ../lib/Lire/Config/XMLSpecListSpec.pm:146 msgid "Custom Title" msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:492 msgid "DLF Schema for ImportJob Logging" msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:452 msgid "DLF Schema for ImportJob and AnalysisJob Statistics" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:136 msgid "DLF Streams" msgstr "DLF Streams" #: ../lib/Lire/OutputFormats/DVI.pm:34 msgid "DVI" msgstr "DVI" #: ../lib/Lire/OutputFormats/DVI.pm:38 msgid "DVI report with charts." msgstr "" #: ../lib/Lire/Config/DlfStreamSpec.pm:39 msgid "Days of DLF to keep" msgstr "Voor hoeveel dagen moet de DLF bewaard blijven?" #: ../lib/Lire/LrCommand.pm:489 #, perl-brace-format msgid "Decompressing log file using {gzip}..." msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:47 msgid "Defines a report section." msgstr "" #: ../lib/Lire/UI/ListWidget.pm:116 ../lib/Lire/UI/ListWidget.pm:143 msgid "Delete" msgstr "Verwijder" #. REFERENCE: lire.xml #: config-spec.pot.pl:188 msgid "" "Demande l'affichage des nombres dans un format lisible. Les unités sont " "échelonnées sur une base décimale donc \"1K requêtes\" signifie \"1000 " "requêtes\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:192 msgid "" "Demande l'affichage du temps dans un format lisible, en utilisant les " "suffixes \"m\", \"h\" et \"d\"." msgstr "" #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:408 msgid "Dessine des aires empilées à la place de barres." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:194 msgid "Directories containing DLF schemas." msgstr "Mappen die DLF schemas bevatten." #: ../lib/Lire/ChartTypes/Dist.pm:35 msgid "Distribution chart" msgstr "Distributie diagram" #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:354 #, fuzzy msgid "Distribution curve" msgstr "Distributie curve" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:476 msgid "Dlf Created" msgstr "Dlf Aangemaakt" #: ../lib/Lire/DlfSchema.pm:148 msgid "Dlf ID" msgstr "Dlf ID" #: ../lib/Lire/DlfSchema.pm:156 msgid "Dlf Source" msgstr "Dlf Source" #: ../lib/Lire/UI/Prefs.pm:103 msgid "Docbook Paths" msgstr "Docbookpaden" #: ../lib/Lire/UI/ListWidget.pm:118 ../lib/Lire/UI/ListWidget.pm:147 msgid "Down" msgstr "Omlaag" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:396 msgid "Défini si les points seront étiquettés ou non." msgstr "" #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:356 msgid "Défini sur une courbe B-spline sera tracée par dessus le diagramme." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:300 msgid "" "Défini un rapport qui peut être utilisé pendant le Report job. Un rapport " "contient une ou plusieurs sections." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:312 msgid "Défini une section d'un rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:310 msgid "Définition de la section" msgstr "" #: ../lib/Lire/LrCommand.pm:319 msgid "ERROR " msgstr "" #: ../lib/Lire/UI/CompoundListWidget.pm:29 #: ../lib/Lire/UI/CompoundListWidget.pm:38 msgid "Edit" msgstr "Wijzig" #: ../lib/Lire/UI.pm:87 #, perl-brace-format msgid "Editing {component}" msgstr "" #: ../lib/Lire/LrCommand.pm:211 msgid "Email related options" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:28 msgid "Encodage utilisé dans le fichier de journal." msgstr "" #. REFERENCE: of_txt.xml #: config-spec.pot.pl:448 msgid "Encodage utilisé dans les rapports formattés." msgstr "" #: ../lib/Lire/LrCommand.pm:546 #, perl-brace-format msgid "Encountered {error_count} errors and ignored {ignored_count} lines." msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:152 msgid "Ends:" msgstr "Eindigt op:" #: ../lib/Lire/UI/StoreWindow.pm:203 msgid "Enter the cleaning date in the form \"YYYY-MM-DD\":" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:266 msgid "Envoyer le rapport formatté par email." msgstr "" #: ../lib/Lire/UI.pm:308 #, perl-brace-format msgid "" "Error creating store:\n" " {error}" msgstr "" "Fout bij maken van store:\n" " {error}" #: ../script/lr_spec2pot.in:158 #, perl-brace-format msgid "Error loading spec '{spec}': {error}" msgstr "Fout bij laden van spec '{spec}': {error}" #: ../lib/Lire/UI.pm:338 #, perl-brace-format msgid "" "Error opening store:\n" " {error}" msgstr "" "Fout bij openen van store:\n" " {error}" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:488 msgid "Errors" msgstr "Fouten" #: ../lib/Lire/OutputFormats/Excel95.pm:38 msgid "Excel95 Spreadsheet" msgstr "Excel 95 Werkblad" #: ../lib/Lire/LrCommand.pm:543 #, perl-brace-format msgid "Extracted {dlf_count} DLF records on {line_count} lines." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:282 msgid "Fichier de configuration de rapport à utiliser." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:198 msgid "File d'entrée du répondeur" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:270 #, fuzzy msgid "File type of the generated report" msgstr "Bestandstype van het gegenereerde rapport" #. REFERENCE: lire.xml #: config-spec.pot.pl:24 msgid "Filtre à appliquer au fichier de journal." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:314 #, fuzzy msgid "Filtres de la section" msgstr "Eerste Sectie" #: ../lib/Lire/ReportParser/HTMLWriter.pm:116 msgid "First Section" msgstr "Eerste Sectie" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:370 config-spec.pot.pl:410 config-spec.pot.pl:430 #, fuzzy msgid "First Y Variable" msgstr "Vierde Y Variabele" #: ../lib/Lire/OutputFormats/Excel95.pm:42 msgid "Format the report as a Excel95 spreadsheet." msgstr "" #: ../script/lr_xml2report.in:17 msgid "" "Formats the XML report and save it in . If " " is omitted, the XML report will be read from STDIN. If " " is omitted, it will be output on STDOUT. Additional " "reports can be merged before formatting the report by using the --template " "and --merge options." msgstr "" #: ../script/lr_xml2mail.in:20 msgid "" "Formats the XML report and sends it by email to the recipients " "specified as argument. Additional reports can be merged before formatting " "the report by using the --template and --merge options." msgstr "" #: ../lib/Lire/LrCommand.pm:757 #, perl-brace-format msgid "Formatting report as {format} and emailing it to {emails}..." msgstr "" #: ../lib/Lire/LrCommand.pm:714 #, fuzzy, perl-brace-format msgid "Formatting report as {format} in {file}..." msgstr "Bezig rapport naar {format} te converteren in {file}..." #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:382 config-spec.pot.pl:422 msgid "Fourth Y Variable" msgstr "Vierde Y Variabele" #. REFERENCE: lire.xml #: config-spec.pot.pl:14 msgid "Gabarit de nom de fichier pour le ReportJob." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:112 msgid "Garder les fichiers intermédiaires" msgstr "" #: ../lib/Lire/LrCommand.pm:619 msgid "Generating XML report..." msgstr "" #. REFERENCE: of_html.xml #: config-spec.pot.pl:440 msgid "Générer ce rapport sur une page unique" msgstr "" #: ../lib/Lire/OutputFormats/HTML.pm:41 msgid "HTML Report with charts, if ploticus is available." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:254 msgid "Horaires de génération des rapports" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:220 msgid "How are week numbers computed?" msgstr "Volgens welke methode worden weeknummers vastgesteld?" #. REFERENCE: lire.xml #: config-spec.pot.pl:274 msgid "Identifiant" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:302 msgid "Identifiant du rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:132 msgid "Identifiant à utiliser pour le programme \"syslog\"" msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:141 msgid "Identifier" msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:142 msgid "" "Identifier that uniquely identifies this specification among the report " "configuration. When two reports are merged, specifications with the same " "identifier are merged together." msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:147 msgid "" "If this parameter is set, its value will be used instead of the display " "title specified in the specification. This string will interpolate $name_ref " "with the parameter's value when the report is generated." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:480 msgid "Ignored Lines" msgstr "Genegeerde Regels" #. REFERENCE: lire.xml #: config-spec.pot.pl:216 msgid "" "Il est de bon aloi de restreindre les privilèges alloués aux processus au " "minimum. Lire ne requiert pas l'utilisation du compte \"root\" pour son " "fonctionnement normal. Il est donc conseillé de créer un compte UNIX dédié. " "Lire vérifie son id d'utilisateur à son démarrage et s'arrête s'il détermine " "qu'il tourne sur le compte du superutilisateur. Cette option vous permet de " "désactiver cette vérification à vos risques et périls." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:102 msgid "" "Il est maintenant possible de personnaliser la présentation de certains " "éléments des rapports HTML. La feuille de style par défaut de Lire pour le " "HTML assure une présentation adéquate mais cette option vous donne la " "possibilité d'utiliser votre propre feuille de style." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:252 msgid "" "Il est necessaire d'identifier les report jobs afin que Lire puisse les " "traiter correctement. Utilisez cette variable pour ce faire. NOTE: Cet " "identifiant ne peut contenir que des caracteres alphanumeriques, des tirets " "et des caracteres de soulignage." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:38 msgid "" "Il est nécessaire d'identifier les import jobs afin que Lire puisse les " "traiter correctement. Utilisez cette variable pour ce faire." msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:42 msgid "Import Jobs" msgstr "Importeer Jobs" #. REFERENCE: lire.xml #: config-spec.pot.pl:22 msgid "ImportJobs configuré dans le store actuel." msgstr "" #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:451 msgid "Important:" msgstr "Belangrijk:" #. REFERENCE: lire.xml #: config-spec.pot.pl:184 msgid "" "Indique à Lire d'afficher les décomptes d'octets dans un format lisible. Une " "échelonnage binaire est opéré, de sorte que \"1Kb\" ait pour valeur \"1024 " "octets\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:202 msgid "Intervale de vérification de la file d'entrée du répondeur" msgstr "" #: ../lib/Lire/UI/CommandWidget.pm:10 msgid "Invalid command" msgstr "Ongeldig commando" #: ../lib/Lire/UI/DirectoryWidget.pm:10 msgid "Invalid directory" msgstr "Ongeldige map" #: ../lib/Lire/UI/ExecutableWidget.pm:10 msgid "Invalid executable" msgstr "" #: ../lib/Lire/UI/FileWidget.pm:96 msgid "Invalid filename" msgstr "Ongeldige bestandsnaam" #: ../script/lr_cron.in:27 #, perl-brace-format msgid "" "Invalid period '{period}'. Should be one of hourly, daily, weekly, monthly " "or yearly.\n" msgstr "" "Ongeldige periode '{period}'. Gebruik één van \"hourly\", \"daily\", " "\"weekly\", \"monthly\" of \"yearly\", voor uurlijks, dagelijks, wekelijks, " "maandelijks en jaarlijks.\n" #. REFERENCE: schema:lire_import_stats #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:468 config-spec.pot.pl:504 msgid "Job Id" msgstr "" #. REFERENCE: schema:lire_import_stats #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:464 config-spec.pot.pl:500 msgid "Job Name" msgstr "" #: ../lib/Lire/LrCommand.pm:101 #, perl-brace-format msgid "Keeping temporary directory {tmpdir}" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:158 msgid "" "L'adresse email à laquelle les utilisateurs du répondeur doivent répondre, " "si différente de la valeur donnée à \"lr_mail_from\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:154 msgid "" "L'adresse spécifiée dans le champ \"From\" des courriels contenant le " "rapport envoyé par le répondeur." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:246 msgid "" "La commande \"ps2pdf\" est nécessaire pour générer des rapports PDF. Elle " "fait partie de la distribution de Ghostscript. Consultez le manuel de " "l'utilisateur pour les adresses de téléchargement." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:280 msgid "" "La fréquence à laquelle cette planification de rapport sera exécutée. La " "valeur de ce paramètre peut être \"hourly\", \"daily\", \"weekly\", \"monthly" "\" or \"yearly\" (\"horaire\", \"quotidien\", \"hebdomadaire\",\"mensuel\" " "ou \"annuel\", respectivement). NOTE: pour générer des rapports " "hebdomadaires, mensuels ou annuels, au moins une planification de rapport " "quotidienne devra être disponible si vous nettoyer votre store DLF. Ce, " "parce que lorsqu'il ne peut trouver les données dans la base de donnée, Lire " "génère ces rapports par un algorithme de jonction dans lequel seuls les " "rapports quotidiens sont considérés." msgstr "" #. REFERENCE: ct_pie.xml #: config-spec.pot.pl:386 msgid "La variable des valeurs" msgstr "" #. REFERENCE: ct_pie.xml #: config-spec.pot.pl:388 msgid "" "La variable numérique qui sera utilisée pour déterminer les aires du " "diagramme." msgstr "" #: ../lib/Lire/OutputFormats/LaTeX.pm:38 msgid "LaTeX" msgstr "LaTeX" #: ../lib/Lire/OutputFormats/LaTeX.pm:42 msgid "LaTeX report with charts." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:119 msgid "Last Section" msgstr "Laatste Sectie" #. REFERENCE: lire.xml #: config-spec.pot.pl:320 msgid "Le diagramme et le sous-rapport qui seront inclus dans la section." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:122 msgid "" "Le service UNIX standard syslog a plusieurs façon de catégoriser les " "messages de journal. Vous pouvez configurer le service syslog pour trier ces " "messages dans différents fichiers selon l'indicateur de facilité. Cette " "option vous permet de sélectionner la facilité que Lire utilisera. Consultez " "la page de manuel syslog.conf(5) pour plus d'information." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:134 msgid "" "Le service UNIX standard syslog permet d'indiquer un identifiant par lequel " "chaque ligne générée par Lire sera marquée. On recommande d'utiliser une " "chaîne de caractères courte et sans espace, comme par exemple \"lire\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:130 msgid "Le service UNIX syslog" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:328 msgid "Le titre de la section qui apparaîtra dans le rapport généré." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:332 msgid "Le titre qui apparaîtra dans le rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:262 msgid "Le type cible du rapport émis." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:260 msgid "" "Les OutputJobs permettent la génération de rapports sous diverses formes et " "en plusieurs formats. Plusieurs peuvent être programmés pour la même période." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:256 msgid "" "Les ReportJobs doivent portent sur une ou plusieurs périodes, chacune " "d'elles étant alors appelée \"planification de rapport\". Une planification " "de rapport vous permet de spécifier quel rapport sera formatté, sa " "configuration ainsi que sa fréquence de génération." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:284 msgid "" "Les fichiers de configuration de rapport sont des fichiers texte avec une " "syntaxe particulière décrivant le type d'informations affichées dans le " "rapport ainsi que sa présentation. Lire est fourni avec un fichier-type de " "configuration pour chaque superservice mais vous pouvez créer le vôtre " "accordé à vos besoins." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:200 msgid "" "Les modules du répondeur automatique de Lire extraient les fichiers journaux " "des courriels, traitent leur contenu et renvoient un courriel à leur " "émetteur. Lorsque le répondeur est activé, il vérifie la présence de " "courriels entrants dans ce répertoire. Consultez le manuel de l'utilisateur " "de Lire pour savoir comment configurer la distribution des courriels vers ce " "répertoire." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:56 msgid "Les requêtes doivent-elles être archivées?" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:68 msgid "" "Les répertoires contenant des initialiseurs de convertisseurs DLF (obsolète)." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:324 #, fuzzy msgid "Les superservices couverts dans cette section." msgstr "De superservice die gebruikt is in deze sectie." #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:390 msgid "Ligne de régression" msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:512 msgid "Line Number" msgstr "Regelnummer" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:508 msgid "Line Type" msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:472 msgid "Lines Read" msgstr "" #: ../lib/Lire/UI/Prefs.pm:102 msgid "Lire Paths" msgstr "Lire Bestandspaden" #: ../lib/Lire/UI/Prefs.pm:60 msgid "Lire Preferences" msgstr "Lire Voorkeuren" #: ../lib/Lire/ReportParser/HTMLWriter.pm:142 msgid "Lire Report" msgstr "Lire Rapport" #. REFERENCE: lire.xml #: config-spec.pot.pl:292 msgid "" "Lire assemble les données par \"superservices\", qui en gros sont des types " "de services. Cette option vous permet de sélectionner le type de données que " "ce report job devra traiter: web, base de données, email ou n'importe quel " "type affiché dans cette liste." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:272 msgid "" "Lire peut formatter ses rapports de différentes façons, du texte simple au " "PDF, plus joli et plus approprié pour l'impression." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:126 msgid "" "Lire peut générer beaucoup d'information de sortie lors de son " "fonctionnement. Si Lire fonctionne via un traitement automatisé comme le " "répondeur ou une tâche cron, il peut être plus approprié d'envoyer ces " "données dans le journal du système pour inspection ultérieure." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:264 msgid "" "Lire peut sauvegarder ses rapports formattés dans un fichier sur le disque " "ou bien l'envoyer par email à une adresse spécifiée. Cette option vous " "permet de déterminer cela." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:316 #, fuzzy msgid "List des filtres qui seront appliqués à cette section." msgstr "Lijst van actieve filters in deze sectie." #. REFERENCE: lire.xml #: config-spec.pot.pl:308 #, fuzzy msgid "List des sections définies dans le rapport." msgstr "Lijst van secties voor het rapport." #. REFERENCE: lire.xml #: config-spec.pot.pl:258 #, fuzzy msgid "List of OutputJobs" msgstr "Lijst van OutputJobs" #: ../lib/Lire/Config/ReportSectionSpec.pm:45 msgid "List of filters that will be applied to this section." msgstr "Lijst van actieve filters in deze sectie." #: ../lib/Lire/Config/ReportSpec.pm:44 msgid "List of sections defined in the report." msgstr "Lijst van secties voor het rapport." #. REFERENCE: lire.xml #: config-spec.pot.pl:296 msgid "Liste d'objets ReportConfig utilisés par ce store." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:60 msgid "Location of the archive" msgstr "Plaats van het archief" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:516 msgid "Log Line" msgstr "" #: ../lib/Lire/LrCommand.pm:484 #, perl-brace-format msgid "Log file was compressed using {algo}." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:58 msgid "" "Lorsque ce paramètre est activé, le répondeur gardera une copie de chaque " "message reçu dans le répertoire spécifié dans la paramètre " "\"lr_archive_dir\"." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:94 msgid "" "Lorsque cette option est active, tous les messages de niveau \"debug\" et " "\"info\" seront dirigés vers stderr ou le journal du " "système - dépendamment de la façon dont Lire est configuré et de si vous " "utilisez la commande lr_run pour invoquer les commandes " "de Lire." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:62 msgid "" "Lorsque l'option \"lr_archive\" est active, le répertoire " "où les requêtes seront archivées." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:204 msgid "" "Lorsque le répondeur est activé, il vérifie souvent la présence de courriels " "dans la file d'entrée. Vous pouvez spécifier la fréquence de vérification " "ici, en minutes." msgstr "" #: ../lib/Lire/LrCommand.pm:255 msgid "" "Merge an additional report before formatting the report. This option can be " "used multipe times." msgstr "" #: ../lib/Lire/LrCommand.pm:245 msgid "Merging options" msgstr "Opties voor samenvoegen" #: ../lib/Lire/LrCommand.pm:672 #, fuzzy, perl-brace-format msgid "Merging reports '{reports}'..." msgstr "bezig rapport naar {format} te converteren" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:520 msgid "Message" msgstr "" #: ../lib/Lire/Error.pm:133 #, perl-brace-format msgid "Missing '{argument}' argument.\n" msgstr "Ontbrekend '{argument}' argument.\n" #. REFERENCE: lire.xml #: config-spec.pot.pl:250 #, fuzzy msgid "Name of the ReportJob." msgstr "Naam van de ReportJob." #. REFERENCE: lire.xml #: config-spec.pot.pl:340 #, fuzzy msgid "Name of the tai64nlocal(1) program." msgstr "Naam van het tai64nlocal(1) programma." #: ../lib/Lire/OutputFormats/XML.pm:38 msgid "" "Native XML format. This keeps the report in Lire Report Markup Language." msgstr "" #: ../lib/Lire/UI.pm:175 ../lib/Lire/UI.pm:195 msgid "New..." msgstr "Nieuw..." #: ../lib/Lire/ReportParser/HTMLWriter.pm:515 msgid "Next" msgstr "Volgende" #: ../lib/Lire/ReportParser/HTMLWriter.pm:122 msgid "Next Page" msgstr "Volgende Pagina" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:41 msgid "No analyser" msgstr "" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:42 msgid "No analyser will be used." msgstr "" #: ../lib/Lire/LrCommand.pm:566 #, perl-brace-format msgid "" "No default report configuration template defined for DLF converter " "\"{converter}.\"." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:281 msgid "No description." msgstr "" #: ../lib/Lire/UI/Prefs.pm:198 ../lib/Lire/UI/CompoundWidget.pm:231 msgid "No help available." msgstr "Geen hulp beschikbaar." #: ../lib/Lire/LrCommand.pm:640 #, perl-brace-format msgid "No report configuration template: {template}." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:408 msgid "No subreports were generated for this section." msgstr "Voor deze sectie zijn geen subrapporten gegenereerd." #: ../lib/Lire/LrCommand.pm:579 #, perl-brace-format msgid "No such DLF converter: {converter}." msgstr "" #: ../lib/Lire/LrCommand.pm:693 #, perl-brace-format msgid "No such output format: {format}." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:36 #, fuzzy msgid "Nom de l'ImportJob." msgstr "Naam van de ReportJob." #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:447 msgid "Note:" msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:478 msgid "Number of DLF records created during the job." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:490 msgid "Number of errors encountered during that job." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:482 msgid "Number of lines ignored during that ImportJob." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:486 msgid "Number of lines saved for later processing during that ImportJob." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:474 msgid "Number of log lines processed during that job." msgstr "" #. REFERENCE: lire.xml #. REFERENCE: of_html.xml #: config-spec.pot.pl:48 config-spec.pot.pl:72 config-spec.pot.pl:74 #: config-spec.pot.pl:76 config-spec.pot.pl:78 config-spec.pot.pl:80 #: config-spec.pot.pl:82 config-spec.pot.pl:84 config-spec.pot.pl:86 #: config-spec.pot.pl:88 config-spec.pot.pl:90 config-spec.pot.pl:104 #: config-spec.pot.pl:106 config-spec.pot.pl:108 config-spec.pot.pl:172 #: config-spec.pot.pl:176 config-spec.pot.pl:206 config-spec.pot.pl:208 #: config-spec.pot.pl:210 config-spec.pot.pl:218 config-spec.pot.pl:224 #: config-spec.pot.pl:230 config-spec.pot.pl:232 config-spec.pot.pl:234 #: config-spec.pot.pl:236 config-spec.pot.pl:348 config-spec.pot.pl:350 #: config-spec.pot.pl:352 config-spec.pot.pl:438 msgid "Obsolete" msgstr "Verouderd" #: ../lib/Lire/LrCommand.pm:203 msgid "Only print errors." msgstr "" #: ../lib/Lire/UI.pm:177 ../lib/Lire/UI.pm:197 msgid "Open..." msgstr "Open..." #: ../lib/Lire/UI/Prefs.pm:101 msgid "Operational Preferences" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:10 msgid "Options spécifiques au fichier de destination choisi." msgstr "" #: ../lib/Lire/LrCommand.pm:228 msgid "Output format options" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:124 msgid "Où envoyer les messages de type progress/debug/warning/error" msgstr "" #: ../lib/Lire/OutputFormats/PDF.pm:37 msgid "PDF" msgstr "" #: ../lib/Lire/OutputFormats/PDF.pm:41 msgid "PDF report with charts." msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:170 msgid "" "Parameters for a chart that should be generated from this subreport's data." msgstr "" #: ../lib/Lire/Config/XMLSpecListSpec.pm:165 msgid "" "Parameters for the charts that should be generated from this subreport's data" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:116 msgid "Paramétrage de LaTeX" msgstr "" #: ../lib/Lire/LrCommand.pm:534 #, perl-brace-format msgid "Parsing log file using {converter} DLF Converter..." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:50 #, fuzzy msgid "Path to Lambda" msgstr "Pad naar Lambda" #. REFERENCE: lire.xml #: config-spec.pot.pl:226 #, fuzzy msgid "Path to odvips" msgstr "Pad naar odvips" #. REFERENCE: lire.xml #: config-spec.pot.pl:244 #, fuzzy msgid "Path to ps2pdf" msgstr "Pad naar ps2pdf" #. REFERENCE: lire.xml #: config-spec.pot.pl:18 #, fuzzy msgid "Path to the gs(1) program." msgstr "Pad naar het gs(1) programma." #. REFERENCE: lire.xml #: config-spec.pot.pl:20 #, fuzzy msgid "Path to the gzip(1) program." msgstr "Pad naar het gzip(1) programma." #. REFERENCE: lire.xml #: config-spec.pot.pl:32 msgid "Path to the log file that will be processed." msgstr "Pad naar het logbestand dat verwerkt zal worden." #. REFERENCE: lire.xml #: config-spec.pot.pl:238 #, fuzzy msgid "Path to the ploticus(1) program." msgstr "Pad naar het ploticus(1) programma." #. REFERENCE: lire.xml #: config-spec.pot.pl:334 #, fuzzy msgid "Path to the sendmail(1) program." msgstr "Pad naar het sendmail(1) programma." #. REFERENCE: lire.xml #: config-spec.pot.pl:344 #, fuzzy msgid "Path to the tar(1) program." msgstr "Pad naar het tar(1) programma." #. REFERENCE: lire.xml #: config-spec.pot.pl:114 msgid "" "Pendant ses traitements, Lire génère des fichiers intermédiaires qu'il " "efface lorsque plus nécessaires. Si vous voulez étudier ou déboguer le " "fonctionnement de Lire, il vous est possible de l'empêcher de les effacer en " "activant cette option. Les fichiers seront conservés dans le répertoire " "indiqué dans la variable d'environnement \"TMPDIR\"." msgstr "" #: ../lib/Lire/ChartTypes/Pie.pm:35 msgid "Pie chart" msgstr "Taartdiagram" #: ../lib/Lire/OutputFormats/Text.pm:37 msgid "Plain Text" msgstr "Platte tekst" #: ../lib/Lire/OutputFormats/Text.pm:41 msgid "Plain Text format." msgstr "" #: ../lib/Lire/ChartTypes/VBars.pm:35 msgid "Plot one or two variables as bars." msgstr "" #: ../lib/Lire/ChartTypes/Lines.pm:35 msgid "Plot one to four variable as lines against another." msgstr "Plot één tot vier variabelen als grafieken van elkaar." #: ../lib/Lire/ChartTypes/Stack.pm:35 msgid "Plot one to four variable stacked one over the other." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:64 msgid "Police utilisée dans les diagrammes" msgstr "" #: ../lib/Lire/OutputFormats/PS.pm:34 msgid "PostScript" msgstr "" #: ../lib/Lire/OutputFormats/PS.pm:38 msgid "PostScript report with charts." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:228 msgid "" "Pour générer des rapports en PostScript ou en PDF, vous devez avoir \"odvips" "\", la version Omega de \"dvips\". Cette commande est fournie avec la " "distribution TeTeX depuis sa version 0.9. Consultez le manuel de " "l'utilisateur pour les informations de télécharment." msgstr "" #: ../lib/Lire/LrCommand.pm:261 ../lib/Lire/LrCommand.pm:280 #, fuzzy msgid "Pre Lire 2.0 report configuration file." msgstr "Rapport Configuratie" #: ../lib/Lire/UI.pm:169 msgid "Preferences..." msgstr "Voorkeuren..." #. REFERENCE: lire.xml #: config-spec.pot.pl:214 msgid "Prevent Lire from being run as root" msgstr "Zorg ervoor dat Lire niet als root uitgevoerd wordt" #: ../lib/Lire/ReportParser/HTMLWriter.pm:509 msgid "Previous" msgstr "Vorige" #: ../lib/Lire/ReportParser/HTMLWriter.pm:120 msgid "Previous Page" msgstr "Vorige Pagina" #: ../lib/Lire/LrCommand.pm:198 msgid "Print Lire version and exit." msgstr "Druk Lire versie af en stop." #: ../lib/Lire/LrCommand.pm:193 msgid "" "Print usage information and exit. If \"report-templates\", \"output-formats" "\" or \"dlf-converters\" is given as argument, the command will print an " "information list for that object type." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:460 msgid "Processing Time" msgstr "" #: ../lib/Lire/UI/Prefs.pm:104 msgid "Program Paths" msgstr "Programmapaden" #: ../lib/Lire/UI/PluginWidget.pm:122 #, perl-brace-format msgid "Properties for {plugin}" msgstr "Eigenschappen voor {plugin}" #. REFERENCE: lire.xml #: config-spec.pot.pl:136 msgid "Quel logo afficher dans l'en-tête des rapports?" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:140 msgid "" "Quelle URI devrait être pointée par le logo affiché dans vos en-têtes de " "rapports." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:100 msgid "" "Quelle feuille de style CSS doit être utilisée pour vos rapports en HTML ?" msgstr "" #: ../lib/Lire/UI.pm:171 msgid "Quit" msgstr "Afsluiten" #: ../lib/Lire/UI/StoreWindow.pm:154 msgid "Records:" msgstr "Records:" #. REFERENCE: lire.xml #: config-spec.pot.pl:54 config-spec.pot.pl:96 config-spec.pot.pl:178 #: config-spec.pot.pl:196 msgid "Remplacé dans logsource." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:110 config-spec.pot.pl:164 config-spec.pot.pl:166 #: config-spec.pot.pl:174 msgid "Remplacé dans report_output." msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:54 msgid "Report Configurations" msgstr "Rapport Configuratie" #: ../lib/Lire/UI/StoreWindow.pm:47 msgid "Report Jobs" msgstr "Rapport Jobs" #: ../lib/Lire/ReportParser/LaTeXWriter.pm:164 #, perl-brace-format msgid "Report for {start} -- {end}" msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:531 #, perl-brace-format msgid "Report generated on: {date}" msgstr "Rapport gegenereerd op: {date}" #: ../lib/Lire/ReportParser/LaTeXWriter.pm:166 #, perl-brace-format msgid "Report generated {date}" msgstr "Rapport gegenereerd op {date}" #: ../lib/Lire/LrCommand.pm:275 msgid "Report generation options" msgstr "Opties voor rapport generatie" #: ../lib/Lire/Config/ReportSpec.pm:36 msgid "Report's identifier" msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:43 msgid "Report's sections" msgstr "Secties van het rapport" #: ../lib/Lire/Config/ReportSpec.pm:39 msgid "Report's title" msgstr "Titel van het rapport" #. REFERENCE: lire.xml #: config-spec.pot.pl:248 msgid "ReportJobs configurés dans le store actuel." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:544 #, perl-brace-format msgid "Reporting on period: {period}" msgstr "Betreft periode: {period}" #: ../lib/Lire/UI/Prefs.pm:99 msgid "Reports" msgstr "Rapporten" #: ../lib/Lire/UI/Prefs.pm:100 msgid "Responder Preferences" msgstr "Voorkeuren voor Responder" #: ../lib/Lire/LrCommand.pm:614 msgid "Running analysers..." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:98 msgid "Répertoires contenant des spécifications de filtres." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:212 msgid "Répertoires contenant les gabarits de spécification de rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:240 msgid "Répertoires contenant les initialiseurs de plugins." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:180 msgid "Répertoires contenant les spécifications de rapports." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:484 msgid "Saved Lines" msgstr "" #: ../lib/Lire/ChartTypes/Scat.pm:35 msgid "Scatterplot of two variables with optional regression line." msgstr "" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #. REFERENCE: ct_vbars.xml #: config-spec.pot.pl:374 config-spec.pot.pl:414 config-spec.pot.pl:434 msgid "Seconde variable en Y" msgstr "" #: ../lib/Lire/Config/ReportSpec.pm:46 msgid "Section definition" msgstr "Sectiedefinitie" #: ../lib/Lire/Config/ReportSectionSpec.pm:38 msgid "Section's Superservice" msgstr "Superservice van de Sectie" #: ../lib/Lire/Config/ReportSectionSpec.pm:51 msgid "Section's content" msgstr "Inhoud van de sectie" #: ../lib/Lire/Config/ReportSectionSpec.pm:44 msgid "Section's filters" msgstr "Filters van de Sectie" #: ../lib/Lire/Config/ReportSectionSpec.pm:34 msgid "Section's title" msgstr "Titel van de Sectie" #. REFERENCE: lire.xml #: config-spec.pot.pl:306 #, fuzzy msgid "Sections du rapport" msgstr "Inhoud van de sectie" #: ../lib/Lire/UI/CommandWidget.pm:14 msgid "Select a Command" msgstr "Kies een Commando" #: ../lib/Lire/UI/DirectoryWidget.pm:18 msgid "Select a Directory" msgstr "Kies een Map" #: ../lib/Lire/UI/FileWidget.pm:100 msgid "Select a File" msgstr "Kies een bestand" #: ../lib/Lire/UI/ExecutableWidget.pm:14 msgid "Select an Executable" msgstr "" #: ../lib/Lire/Config/DlfAnalyserSpec.pm:80 #, perl-brace-format msgid "" "Select the analyser to use to create {schema} DLF records. If you select " "'none', no records will be created. Otherwise, the selected analyser will be " "run after each ImportJob that created records in the Dlf stream used by the " "analyser." msgstr "" #: ../lib/Lire/LrCommand.pm:236 msgid "Select the output format. Default to \"txt\"" msgstr "" #: ../lib/Lire/LrCommand.pm:285 msgid "" "Select the report configuration template that should be used for generating " "the report." msgstr "" #: ../lib/Lire/LrCommand.pm:249 msgid "" "Select the report configuration template that should be used for merging the " "reports. This option is required if you use the --merge option." msgstr "" #: ../lib/Lire/LrCommand.pm:266 msgid "" "Selects the superservice for which the report configuration file is made." msgstr "" #: ../lib/Lire/LrCommand.pm:214 msgid "Sets the email's subject." msgstr "" #: ../script/lr_log2mail.in:22 msgid "Sets the log file to convert instead of reading it from STDIN." msgstr "" #. REFERENCE: of_html.xml #: config-spec.pot.pl:442 msgid "" "Si vous désirez voir apparaître votre rapport sur une seule page, activez " "cette option. Autrement un document à plusieurs pages sera généré." msgstr "" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:368 msgid "" "Si vous indiquez une variable numérique, elle sera utilisée pour l'axe des X " "à la place de la variable \"case_var\"." msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:392 msgid "Spécifie si une ligne de régression sera dessinée ou non." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:456 msgid "Start Time" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:150 msgid "Starts:" msgstr "Start op:" #. REFERENCE: lire.xml #: config-spec.pot.pl:268 msgid "Store the formatted output into a file." msgstr "Bewaar de geformateerde uitvoer in een bestand." #: ../lib/Lire/UI/StoreWindow.pm:75 msgid "Store: " msgstr "Store: " #. REFERENCE: lire.xml #: config-spec.pot.pl:6 msgid "Sujet du courriel contenant le rapport." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:322 #, fuzzy msgid "Superservice de la section" msgstr "De superservice die gebruikt is in deze sectie." #. REFERENCE: lire.xml #: config-spec.pot.pl:290 msgid "Sélectionner le superservice pour ce rapport." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:114 #: ../lib/Lire/ReportParser/HTMLWriter.pm:426 #: ../lib/Lire/ReportParser/HTMLWriter.pm:431 #: ../lib/Lire/ReportParser/HTMLWriter.pm:503 msgid "Table Of Contents" msgstr "Inhoudsopgave" #. REFERENCE: lire.xml #: config-spec.pot.pl:144 config-spec.pot.pl:160 msgid "Texte d'avis de non-responsabilité du répondeur automatique" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:148 msgid "Texte d'explication du répondeur automatique" msgstr "" #: ../lib/Lire/LrCommand.pm:654 msgid "The -U option is required with --report-cfg" msgstr "" #: ../lib/Lire/Config/ChartSpec.pm:35 msgid "" "The basename of the chart. An extension will be appended based on the " "chart's format. If this attribute isn't set, the Subreport'id will be used." msgstr "" #: ../lib/Lire/Config/ChartSpec.pm:49 msgid "" "The categorical variable that will be used to select the case that will make " "the chart's data." msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:52 msgid "The chart and subreport that will be included in this section." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:518 msgid "The content of the log line." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:462 msgid "The duration of the job." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:506 msgid "" "The job id in which that line was processed. This is the job name plus the " "timestamp of the start of the job. " msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:470 msgid "" "The job id to which the stats relate to. This is the job name plus the " "timestamp of the start of the job. The job id makes it possible to " "distinguish between different run of the same scheduled import or analysis " "job. " msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:514 msgid "The log line number." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:502 msgid "The name of the ImportJob to which that log line is related." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:466 msgid "The name of the job." msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:35 msgid "The section's title that will appear in the generated report." msgstr "" #: ../lib/Lire/Config/ReportSectionSpec.pm:39 msgid "The superservices that is used by this section." msgstr "De superservice die gebruikt is in deze sectie." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:498 msgid "The time at which that log line was processed." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:458 msgid "The time at which the job was started." msgstr "" #: ../lib/Lire/Config/ChartSpec.pm:40 msgid "The title that will appear on the chart." msgstr "De titel die zal worden weergegeven op de grafiek." #: ../lib/Lire/Config/ChartSpec.pm:44 msgid "The type of charts to generate. Chart types are plugins." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:310 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:280 msgid "There is no entries in this table." msgstr "" #. REFERENCE: schema:lire_import_stats #: config-spec.pot.pl:454 msgid "This Dlf schema is used to store ImportJob and AnalysisJob statistics." msgstr "" #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:494 msgid "" "This Dlf schema is used to store information related to importation and " "analysis jobs. It is this Dlf stream that will contains the lines that were " "marked for continuation, that were ignored or that had errors during an " "importation process. " msgstr "" #: ../lib/Lire/LrCommand.pm:742 msgid "This command requires the MIME::Tools CPAN module." msgstr "" #: ../lib/Lire/Config/DlfStreamSpec.pm:68 msgid "" "This configures the analysers that should be run on this DlfStream as well " "as the number of days of data to keep." msgstr "" #: ../lib/Lire/DlfSchema.pm:158 msgid "" "This field contains an identifier relating the record to the process\n" "that created it.\n" msgstr "" "Dit veld bevat een sleutel die het record relateert aan het process\n" "dat het record gemaakt heeft.\n" #: ../lib/Lire/DlfSchema.pm:150 msgid "" "This field contains an integer which uniquely identify this DLF record\n" "in the stream.\n" msgstr "" "Dit veld bevat een integer die dit DLF record in de stream\n" "identificeert.\n" #: ../lib/Lire/Config/ReportSpec.pm:37 msgid "This identifier can be used to refer to this report configuration." msgstr "" #: ../lib/Lire/LrCommand.pm:396 msgid "This option is obsolete." msgstr "" #: ../lib/Lire/LrCommand.pm:700 msgid "This output format has missing requirements:" msgstr "" #: ../lib/Lire/Config/DlfStreamSpec.pm:41 msgid "" "This parameter states how many days of DLF records you want to keep in the " "DlfStore. Records older than this number of days will be deleted. Use 0 to " "never expires records." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:363 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:214 #, perl-brace-format msgid "This report is missing: {reason}" msgstr "Dit rapport ontbreekt: {reason}" #. REFERENCE: lire.xml #: config-spec.pot.pl:70 #, fuzzy msgid "This variable is superseded by plugins_init_path." msgstr "" "Voor deze variabele wordt nu plugins_init_path gebruikt." #. REFERENCE: schema:lire_import_log #: config-spec.pot.pl:496 msgid "Timestamp" msgstr "Tijdstip" #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:449 msgid "Tip:" msgstr "Tip:" #. REFERENCE: lire.xml #: config-spec.pot.pl:326 msgid "Titre de la section" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:330 msgid "Titre du rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:52 msgid "" "To generate DVI, PostScript or PDF reports you need Lambda which is the " "Omega version of LaTeX. It is bundled with the TeTeX distribution since " "version 0.9. See the User Manual for download locations." msgstr "" "Om DVI, Postscript of PDF rapporten te genereren, heeft u Lambda nodig. Dat " "is de Omega versie van LaTeX, en wordt geleverd met de TeTeX distributie " "sinds versie 0.9. In de Gebruikers Handleiding kunt u vinden waar u dit " "kunt downloaden." #: ../lib/Lire/ReportParser/HTMLWriter.pm:221 #: ../lib/Lire/ReportParser/LaTeXWriter.pm:334 #, perl-brace-format msgid "Total for {nrecords} records" msgstr "Totaal voor {nrecords} record(s)" #. REFERENCE: ct_lines.xml #. REFERENCE: ct_stack.xml #: config-spec.pot.pl:378 config-spec.pot.pl:418 msgid "Troisième variable en Y" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:44 #, fuzzy msgid "Type of the logfile." msgstr "Type van het logbestand." #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:360 msgid "" "Une variable numérique pour laquelle la distribution sera tracée pour les " "cas choisis pour \"case_var\"." msgstr "" #: ../lib/Lire/ReportParser/HTMLWriter.pm:542 msgid "Unknown Period" msgstr "Onbekende Periode" #: ../lib/Lire/Error.pm:154 #, perl-brace-format msgid "Unknown command: '{command}'.\n" msgstr "Onbekend commando: '{command}'.\n" #: ../lib/Lire/LrCommand.pm:387 #, perl-brace-format msgid "Unknown help section: {section}" msgstr "" #: ../lib/Lire/UI/ListWidget.pm:117 ../lib/Lire/UI/ListWidget.pm:145 msgid "Up" msgstr "Omhoog" #: ../script/lr_cron.in:21 msgid "Usage: lr_cron \n" msgstr "Gebruik: lr_cron \n" #: ../script/lr_report_cfg2xml.in:22 msgid "Usage: lr_report_cfg2xml \n" msgstr "Gebruik: lr_report_cfg2xml \n" #: ../script/lr_spec2pot.in:27 #, fuzzy msgid "" "Usage: lr_spec2pot [--cfgspecdir ]*\n" " [--reportsdir ]*\n" " [--filtersdir ]*\n" " [--pluginsdir ]*\n" " [--schemasdir ]* +\n" msgstr "" "Gebruik: lr_spec2pot [--cfgspecdir ]\n" " [--reportsdir ]* [--filtersdir ]*\n" " [--schemasdir ]* +\n" #: ../lib/Lire/LrCommand.pm:370 #, perl-brace-format msgid "Usage: {program} {usage}" msgstr "" #: ../lib/Lire/LrCommand.pm:581 msgid "Use --help dlf-converters to list available converters" msgstr "" #: ../lib/Lire/LrCommand.pm:695 msgid "Use --help output-formats to list available formats." msgstr "" #: ../lib/Lire/LrCommand.pm:642 msgid "Use --help report-templates to list available templates." msgstr "" #. REFERENCE: of_html.xml #: config-spec.pot.pl:444 #, fuzzy msgid "Use XHTML 1.0 syntax" msgstr "Gebruik XHTML 1.0 syntax" #: ../lib/Lire/LrCommand.pm:568 msgid "Use the --template option." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:30 msgid "" "Utilisez ce paramètre au cas où vos fichiers journaux sont encodés dans une " "format différent de votre système." msgstr "" #. REFERENCE: of_txt.xml #: config-spec.pot.pl:450 msgid "" "Utilisez ce paramètre au cas où vous désirez formatter vos rapports dans un " "encodage différent de celui utilisé par votre système." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:66 msgid "" "Utilisez cette option pour contrôler la fonte que Ploticus utilisera pour le " "rendu des caractères. Les fontes disponibles dépendent du format d'image " "choisi. Consultez la documentation pour plus de détails." msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:156 msgid "Valeur de l'en-tête de courriel \"Reply-To\"" msgstr "" #. REFERENCE: ct_dist.xml #: config-spec.pot.pl:358 #, fuzzy msgid "Variable" msgstr "Variabele" #. REFERENCE: ct_lines.xml #: config-spec.pot.pl:366 msgid "Variable numérique des X" msgstr "" #: ../lib/Lire/LrCommand.pm:330 msgid "WARNING " msgstr "" #: ../lib/Lire/ReportParser/LaTeXDocBookFormatter.pm:448 msgid "Warning:" msgstr "" #. REFERENCE: of_html.xml #: config-spec.pot.pl:446 msgid "" "XHTML is the modern form of HTML. XHTML files are actually XML files with an " "HTML vocabulary. Since XHTML 1.0 is just a little bit more than HTML 4.01, " "the result displayed will not change considerably but certain people like to " "live on the bleeding edge..." msgstr "" "XHTML is de moderne vorm van HTML. XHTML bestanden zijn in feite XML " "bestanden met een HTML vocabulair. Omdat XHTML 1.0 slechts een klein beetje " "meer bevat dan HTML 4.01 zal het resultaat dat getoond wordt nauwelijks " "merkbaar anders zijn. Sommigen gebruiken echter liefst het allernieuwste..." #: ../lib/Lire/OutputFormats/XML.pm:34 msgid "XML" msgstr "" #: ../script/lr_log2mail.in:30 ../script/lr_xml2mail.in:26 msgid "You need at least one email argument." msgstr "" #: ../lib/Lire/LrCommand.pm:659 msgid "You need to use the --template option to merge reports." msgstr "Gebruik de --template optie om rapporten samen te voegen." #: ../lib/Lire/LrCommand.pm:756 #, perl-brace-format msgid "Your {format} report." msgstr "Uw {format} rapport." #: ../script/lr_xml2mail.in:19 msgid "[] +" msgstr "" #: ../script/lr_xml2report.in:16 msgid "[] [ []]" msgstr "" #: ../script/lr_log2mail.in:23 msgid "[] +" msgstr "" #: ../script/lr_log2report.in:18 msgid "[] [ []]" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:163 msgid "[Clean]" msgstr "" #: ../lib/Lire/UI/StoreWindow.pm:161 msgid "[Configure]" msgstr "[Configureer]" #: ../lib/Lire/ReportParser/LaTeXWriter.pm:330 msgid "continued on next page" msgstr "" #: ../lib/Lire/Error.pm:69 ../lib/Lire/Error.pm:78 #, perl-brace-format msgid "could not open '{file}' for reading: {error}" msgstr "bestand '{file}' kon niet geopend worden om te lezen: {error}" #: ../lib/Lire/Error.pm:87 #, perl-brace-format msgid "could not open '{file}' for writing: {error}" msgstr "bestand '{file}' kon niet geopende worden om te schrijven: {error}" #: ../lib/Lire/Error.pm:141 #, perl-brace-format msgid "directory '{directory}' already exists" msgstr "map '{directory}' bestaat al" #: ../lib/Lire/LrCommand.pm:493 #, fuzzy, perl-brace-format msgid "error forking: {error}" msgstr "Er trad een fout op: {error}" #: ../lib/Lire/Error.pm:61 #, perl-brace-format msgid "file '{file}' is empty" msgstr "bestand '{file}' is leeg" #: ../lib/Lire/LrCommand.pm:508 #, perl-brace-format msgid "gzip exited with non zero status: {status}" msgstr "gzip is gestopt met een niet-nul status: {status}" #: ../lib/Lire/LrCommand.pm:486 msgid "gzip(1) isn't available" msgstr "gzip(1) is niet beschikbaar" #: ../lib/Lire/Error.pm:96 #, perl-brace-format msgid "invalid option: '{option}'" msgstr "ongeldige optie: '{option}'" #: ../lib/Lire/Error.pm:104 #, perl-brace-format msgid "invalid superservice: '{superservice}'" msgstr "ongeldige superservice: '{superservice}'" #: ../lib/Lire/Config/Scalar.pm:59 #, perl-brace-format msgid "invalid value for parameter '{parameter}': {value}" msgstr "ongeldige waarde voor parameter '{parameter}': {value}" #: ../lib/Lire/Error.pm:125 #, perl-brace-format msgid "missing '{argument}' argument" msgstr "ontbrekend argument '{argument}'" #: ../lib/Lire/Error.pm:117 #, perl-brace-format msgid "missing '{command}' command" msgstr "ontbrekend commando '{command}'" #: ../lib/Lire/OutputFormats/Excel95.pm:46 msgid "missing CPAN module Spreadsheet::WriteExcel" msgstr "ontbrekende CPAN module Spreadsheet::WriteExcel" #: ../lib/Lire/Error.pm:114 #, perl-brace-format msgid "missing {make} '{command}' command" msgstr "ontbrekend {make} '{command}' commando" #: ../lib/Lire/UI/BoolWidget.pm:27 msgid "no" msgstr "nee" #: ../lib/Lire/LrCommand.pm:478 ../lib/Lire/LrCommand.pm:505 #, perl-brace-format msgid "read failed: {error}" msgstr "" #: ../script/lr_spec2pot.in:123 msgid "" "specs are strings of the form schema:, filter::, report:" ":, config_spec: or report_cfg:\n" msgstr "" "specs zijn strings van de vorm schema:, filter::, report:" ":, config_spec: or report_cfg:\n" #: ../lib/Lire/Error.pm:146 msgid "too many arguments" msgstr "te veel argumenten" #: ../lib/Lire/UI/BoolWidget.pm:27 msgid "yes" msgstr "ja" #: ../lib/Lire/LrCommand.pm:349 #, perl-brace-format msgid "{program} as shipped with Lire version {version}" msgstr "{program}, als geleverd met Lire {version}" #. REFERENCE: lire.xml #: config-spec.pot.pl:278 msgid "À quelle fréquence désirez-vous générer ce rapport" msgstr "" #. REFERENCE: lire.xml #: config-spec.pot.pl:40 msgid "À quelle fréquencer importer le journal dans le store" msgstr "" #. REFERENCE: ct_scat.xml #: config-spec.pot.pl:394 msgid "Étiquetter les points" msgstr "" #, fuzzy #~ msgid "De superservice die gebruikt is in deze sectie." #~ msgstr "De superservice die gebruikt is in deze sectie." #, fuzzy #~ msgid "Eerste Y variabele" #~ msgstr "Eerste Y variabele" #, fuzzy #~ msgid "Kort hoeveelheid bytes (Kb, Mb, ...) af" #~ msgstr "Kort hoeveelheid bytes (Kb, Mb, ...) af" #, fuzzy #~ msgid "Lijst van secties voor het rapport." #~ msgstr "Lijst van secties voor het rapport." #, fuzzy #~ msgid "Rapport Configuratie" #~ msgstr "Rapport Configuratie" #, fuzzy #~ msgid "Sectiedefinitie" #~ msgstr "Sectiedefinitie" #~ msgid "UNIX syslog daemon" #~ msgstr "UNIX syslog daemon" #, fuzzy #~ msgid "Vierde Y Variabele" #~ msgstr "Eerste Y variabele" #~ msgid "DLF records for {time}." #~ msgstr "DLF records voor {time}" lire-2.1.1/all/po/lire-xml-stamp0000644000175000017500000000000011677606224013354 00000000000000lire-2.1.1/all/po/config-spec.pot.pl0000644000175000017500000006777611677606225014153 00000000000000# REFERENCE: lire.xml __( q{Adresse de courriel où envoyer le rapport.} ); # REFERENCE: lire.xml __( q{A report output can be emailed to many addresses at the same time. Fill in this list with those. At least one address is required.} ); # REFERENCE: lire.xml __( q{Sujet du courriel contenant le rapport.} ); # REFERENCE: lire.xml __( q{Ce paramètre pour permet d'indiquer le sujet qui apparaîtra dans les courriels générés automatiquement afin d'identifier les rapports reçus.} ); # REFERENCE: lire.xml __( q{Options spécifiques au fichier de destination choisi.} ); # REFERENCE: lire.xml __( q{Cette option vous permet de configurer les différents attributs (un seul est disponible pour l'instant) du fichier généré.} ); # REFERENCE: lire.xml __( q{Gabarit de nom de fichier pour le ReportJob.} ); # REFERENCE: lire.xml __( q{Ceci est un gabarit de nom de fichier pouvant contenir une interpolation fournie par strftime(3).} ); # REFERENCE: lire.xml __( q{Path to the gs(1) program.} ); # REFERENCE: lire.xml __( q{Path to the gzip(1) program.} ); # REFERENCE: lire.xml __( q{ImportJobs configuré dans le store actuel.} ); # REFERENCE: lire.xml __( q{Filtre à appliquer au fichier de journal.} ); # REFERENCE: lire.xml __( q{Certains fichiers de journaux requiert un traitement préalable avant de passer au travers du moteur principale de Lire. La commande zcat est un filtre typique utilisé pour décompresser les fichiers compressés par gzip ou compress à la volée.} ); # REFERENCE: lire.xml __( q{Encodage utilisé dans le fichier de journal.} ); # REFERENCE: lire.xml __( q{Utilisez ce paramètre au cas où vos fichiers journaux sont encodés dans une format différent de votre système.} ); # REFERENCE: lire.xml __( q{Path to the log file that will be processed.} ); # REFERENCE: lire.xml __( q{Ceci représente le chemin d'accès au fichier journal qui doit être importé. Ce chemin d'accès peut correspondre à un gabarit formatté selon la spécification de strftime(3). Par exemple, /var/log/apache/corp.com%Y%m%d.log.gz sera remplacé par quelque chose semblable à /var/log/apache/corp.com20040124.log.gz.} ); # REFERENCE: lire.xml __( q{Nom de l'ImportJob.} ); # REFERENCE: lire.xml __( q{Il est nécessaire d'identifier les import jobs afin que Lire puisse les traiter correctement. Utilisez cette variable pour ce faire.} ); # REFERENCE: lire.xml __( q{À quelle fréquencer importer le journal dans le store} ); # REFERENCE: lire.xml __( q{Chaque Import Job peut avoir sa propre période d'importation. Les jobs cron mensuels et annuels sont exécutés le premier jour du mois ou de l'année tandis que les hebdomadaires le sont le lundi matin à minuit.} ); # REFERENCE: lire.xml __( q{Type of the logfile.} ); # REFERENCE: lire.xml __( q{Ce paramètre indique le service par lequel le fichier journal spécifié a été produit. Ce paramètre est obligatoire puisque Lire ne peut le déduire autrement.} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Path to Lambda} ); # REFERENCE: lire.xml __( q{To generate DVI, PostScript or PDF reports you need Lambda which is the Omega version of LaTeX. It is bundled with the TeTeX distribution since version 0.9. See the User Manual for download locations.} ); # REFERENCE: lire.xml __( q{Remplacé dans logsource.} ); # REFERENCE: lire.xml __( q{Les requêtes doivent-elles être archivées?} ); # REFERENCE: lire.xml __( q{Lorsque ce paramètre est activé, le répondeur gardera une copie de chaque message reçu dans le répertoire spécifié dans la paramètre "lr_archive_dir".} ); # REFERENCE: lire.xml __( q{Location of the archive} ); # REFERENCE: lire.xml __( q{Lorsque l'option "lr_archive" est active, le répertoire où les requêtes seront archivées.} ); # REFERENCE: lire.xml __( q{Police utilisée dans les diagrammes} ); # REFERENCE: lire.xml __( q{Utilisez cette option pour contrôler la fonte que Ploticus utilisera pour le rendu des caractères. Les fontes disponibles dépendent du format d'image choisi. Consultez la documentation pour plus de détails.} ); # REFERENCE: lire.xml __( q{Les répertoires contenant des initialiseurs de convertisseurs DLF (obsolète).} ); # REFERENCE: lire.xml __( q{This variable is superseded by plugins_init_path.} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Activer l'affichage d'information de débogage} ); # REFERENCE: lire.xml __( q{Lorsque cette option est active, tous les messages de niveau "debug" et "info" seront dirigés vers stderr ou le journal du système - dépendamment de la façon dont Lire est configuré et de si vous utilisez la commande lr_run pour invoquer les commandes de Lire.} ); # REFERENCE: lire.xml __( q{Remplacé dans logsource.} ); # REFERENCE: lire.xml __( q{Répertoires contenant des spécifications de filtres.} ); # REFERENCE: lire.xml __( q{Quelle feuille de style CSS doit être utilisée pour vos rapports en HTML ?} ); # REFERENCE: lire.xml __( q{Il est maintenant possible de personnaliser la présentation de certains éléments des rapports HTML. La feuille de style par défaut de Lire pour le HTML assure une présentation adéquate mais cette option vous donne la possibilité d'utiliser votre propre feuille de style.} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Remplacé dans report_output.} ); # REFERENCE: lire.xml __( q{Garder les fichiers intermédiaires} ); # REFERENCE: lire.xml __( q{Pendant ses traitements, Lire génère des fichiers intermédiaires qu'il efface lorsque plus nécessaires. Si vous voulez étudier ou déboguer le fonctionnement de Lire, il vous est possible de l'empêcher de les effacer en activant cette option. Les fichiers seront conservés dans le répertoire indiqué dans la variable d'environnement "TMPDIR".} ); # REFERENCE: lire.xml __( q{Paramétrage de LaTeX} ); # REFERENCE: lire.xml __( q{Cette option peut être utilisée pour inclure du code LaTeX qui sera inséré dans les rapports formattés (qui incluent ceux aux formats DVI, PS et PDF). Ceci permet de personnaliser les en-têtes et les fontes.} ); # REFERENCE: lire.xml __( q{Choix de la facilité "syslog" à utiliser} ); # REFERENCE: lire.xml __( q{Le service UNIX standard syslog a plusieurs façon de catégoriser les messages de journal. Vous pouvez configurer le service syslog pour trier ces messages dans différents fichiers selon l'indicateur de facilité. Cette option vous permet de sélectionner la facilité que Lire utilisera. Consultez la page de manuel syslog.conf(5) pour plus d'information.} ); # REFERENCE: lire.xml __( q{Où envoyer les messages de type progress/debug/warning/error} ); # REFERENCE: lire.xml __( q{Lire peut générer beaucoup d'information de sortie lors de son fonctionnement. Si Lire fonctionne via un traitement automatisé comme le répondeur ou une tâche cron, il peut être plus approprié d'envoyer ces données dans le journal du système pour inspection ultérieure.} ); # REFERENCE: lire.xml __( q{Canal de sortie des erreurs (terminal ou redirection vers un fichier)} ); # REFERENCE: lire.xml __( q{Le service UNIX syslog} ); # REFERENCE: lire.xml __( q{Identifiant à utiliser pour le programme "syslog"} ); # REFERENCE: lire.xml __( q{Le service UNIX standard syslog permet d'indiquer un identifiant par lequel chaque ligne générée par Lire sera marquée. On recommande d'utiliser une chaîne de caractères courte et sans espace, comme par exemple "lire".} ); # REFERENCE: lire.xml __( q{Quel logo afficher dans l'en-tête des rapports?} ); # REFERENCE: lire.xml __( q{Certains format de rapport (HTML, PDF, ...) supportent l'inclusion d'images. Il est alors possible d'associer un logo à ces rapports, comme par exemple le logo de Lire adjoint par défaut ou encore celui de votre entreprise. Ce paramètre peut représenter un fichier sur votre système de fichier local ou bien une URL.} ); # REFERENCE: lire.xml __( q{Quelle URI devrait être pointée par le logo affiché dans vos en-têtes de rapports.} ); # REFERENCE: lire.xml __( q{Certains formats de rapport supportent la gestion des hyperliens (HTML, PDF, ...). Dans ce cas, il est possible d'en associer un au logo d'en-tête. Par défaut, ce lien pointe vers le site web de la fondation LogReport. Si vous ne désirez lui associer aucun hyperlien, laissez ce champ vide.} ); # REFERENCE: lire.xml __( q{Texte d'avis de non-responsabilité du répondeur automatique} ); # REFERENCE: lire.xml __( q{Ce fichier est ajouté aux courriels renvoyés par le répondeur automatique.} ); # REFERENCE: lire.xml __( q{Texte d'explication du répondeur automatique} ); # REFERENCE: lire.xml __( q{Ce fichier sera placé au début des courriels renvoyés par le répondeur automatique.} ); # REFERENCE: lire.xml __( q{Adresse de courriel à partir de laquelle envoyer le rapport.} ); # REFERENCE: lire.xml __( q{L'adresse spécifiée dans le champ "From" des courriels contenant le rapport envoyé par le répondeur.} ); # REFERENCE: lire.xml __( q{Valeur de l'en-tête de courriel "Reply-To"} ); # REFERENCE: lire.xml __( q{L'adresse email à laquelle les utilisateurs du répondeur doivent répondre, si différente de la valeur donnée à "lr_mail_from".} ); # REFERENCE: lire.xml __( q{Texte d'avis de non-responsabilité du répondeur automatique} ); # REFERENCE: lire.xml __( q{Ce fichier en texte simple est ajouté aux courriels renvoyés par le répondeur automatique.} ); # REFERENCE: lire.xml __( q{Remplacé dans report_output.} ); # REFERENCE: lire.xml __( q{Remplacé dans report_output.} ); # REFERENCE: lire.xml __( q{Chemin d'accès à l'ancien fichier address.cf.} ); # REFERENCE: lire.xml __( q{Chemin d'accès au répertoire contenant les anciens convertisseurs DLF.} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Remplacé dans report_output.} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Remplacé dans logsource.} ); # REFERENCE: lire.xml __( q{Répertoires contenant les spécifications de rapports.} ); # REFERENCE: lire.xml __( q{Abbreviate byte counts (Kb, Mb, ...)} ); # REFERENCE: lire.xml __( q{Indique à Lire d'afficher les décomptes d'octets dans un format lisible. Une échelonnage binaire est opéré, de sorte que "1Kb" ait pour valeur "1024 octets".} ); # REFERENCE: lire.xml __( q{Abbreviate numbers (Kb, Mb, ...)} ); # REFERENCE: lire.xml __( q{Demande l'affichage des nombres dans un format lisible. Les unités sont échelonnées sur une base décimale donc "1K requêtes" signifie "1000 requêtes".} ); # REFERENCE: lire.xml __( q{Abbreviate time units (minutes, hours, ...)} ); # REFERENCE: lire.xml __( q{Demande l'affichage du temps dans un format lisible, en utilisant les suffixes "m", "h" et "d".} ); # REFERENCE: lire.xml __( q{Directories containing DLF schemas.} ); # REFERENCE: lire.xml __( q{Remplacé dans logsource.} ); # REFERENCE: lire.xml __( q{File d'entrée du répondeur} ); # REFERENCE: lire.xml __( q{Les modules du répondeur automatique de Lire extraient les fichiers journaux des courriels, traitent leur contenu et renvoient un courriel à leur émetteur. Lorsque le répondeur est activé, il vérifie la présence de courriels entrants dans ce répertoire. Consultez le manuel de l'utilisateur de Lire pour savoir comment configurer la distribution des courriels vers ce répertoire.} ); # REFERENCE: lire.xml __( q{Intervale de vérification de la file d'entrée du répondeur} ); # REFERENCE: lire.xml __( q{Lorsque le répondeur est activé, il vérifie souvent la présence de courriels dans la file d'entrée. Vous pouvez spécifier la fréquence de vérification ici, en minutes.} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Répertoires contenant les gabarits de spécification de rapport.} ); # REFERENCE: lire.xml __( q{Prevent Lire from being run as root} ); # REFERENCE: lire.xml __( q{Il est de bon aloi de restreindre les privilèges alloués aux processus au minimum. Lire ne requiert pas l'utilisation du compte "root" pour son fonctionnement normal. Il est donc conseillé de créer un compte UNIX dédié. Lire vérifie son id d'utilisateur à son démarrage et s'arrête s'il détermine qu'il tourne sur le compte du superutilisateur. Cette option vous permet de désactiver cette vérification à vos risques et périls.} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{How are week numbers computed?} ); # REFERENCE: lire.xml __( q{Avec "W", les semaines sont numérotées de 00 à 53 en prenant comme point de départ le premier lundi de la semaine 01. Avec "U", les semaines sont numérotées de la même façon en tenant compte du dimanche comme premier jour de la semaine; tandis qu'avec "ISO", les semaines sont calculées selon le standard ISO 8601:1988, de 01 à 53, avec comme semaine 01 celle qui contient au moins 4 jours dans l'année courante en prenant lundi comme premier jour.} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Path to odvips} ); # REFERENCE: lire.xml __( q{Pour générer des rapports en PostScript ou en PDF, vous devez avoir "odvips", la version Omega de "dvips". Cette commande est fournie avec la distribution TeTeX depuis sa version 0.9. Consultez le manuel de l'utilisateur pour les informations de télécharment.} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Path to the ploticus(1) program.} ); # REFERENCE: lire.xml __( q{Répertoires contenant les initialiseurs de plugins.} ); # REFERENCE: lire.xml __( q{A list of directories which contain initialization scripts. These are short perl script that should register plugins with the Lire::PluginManager.} ); # REFERENCE: lire.xml __( q{Path to ps2pdf} ); # REFERENCE: lire.xml __( q{La commande "ps2pdf" est nécessaire pour générer des rapports PDF. Elle fait partie de la distribution de Ghostscript. Consultez le manuel de l'utilisateur pour les adresses de téléchargement.} ); # REFERENCE: lire.xml __( q{ReportJobs configurés dans le store actuel.} ); # REFERENCE: lire.xml __( q{Name of the ReportJob.} ); # REFERENCE: lire.xml __( q{Il est necessaire d'identifier les report jobs afin que Lire puisse les traiter correctement. Utilisez cette variable pour ce faire. NOTE: Cet identifiant ne peut contenir que des caracteres alphanumeriques, des tirets et des caracteres de soulignage.} ); # REFERENCE: lire.xml __( q{Horaires de génération des rapports} ); # REFERENCE: lire.xml __( q{Les ReportJobs doivent portent sur une ou plusieurs périodes, chacune d'elles étant alors appelée "planification de rapport". Une planification de rapport vous permet de spécifier quel rapport sera formatté, sa configuration ainsi que sa fréquence de génération.} ); # REFERENCE: lire.xml __( q{List of OutputJobs} ); # REFERENCE: lire.xml __( q{Les OutputJobs permettent la génération de rapports sous diverses formes et en plusieurs formats. Plusieurs peuvent être programmés pour la même période.} ); # REFERENCE: lire.xml __( q{Le type cible du rapport émis.} ); # REFERENCE: lire.xml __( q{Lire peut sauvegarder ses rapports formattés dans un fichier sur le disque ou bien l'envoyer par email à une adresse spécifiée. Cette option vous permet de déterminer cela.} ); # REFERENCE: lire.xml __( q{Envoyer le rapport formatté par email.} ); # REFERENCE: lire.xml __( q{Store the formatted output into a file.} ); # REFERENCE: lire.xml __( q{File type of the generated report} ); # REFERENCE: lire.xml __( q{Lire peut formatter ses rapports de différentes façons, du texte simple au PDF, plus joli et plus approprié pour l'impression.} ); # REFERENCE: lire.xml __( q{Identifiant} ); # REFERENCE: lire.xml __( q{An identifier for this output job.} ); # REFERENCE: lire.xml __( q{À quelle fréquence désirez-vous générer ce rapport} ); # REFERENCE: lire.xml __( q{La fréquence à laquelle cette planification de rapport sera exécutée. La valeur de ce paramètre peut être "hourly", "daily", "weekly", "monthly" or "yearly" ("horaire", "quotidien", "hebdomadaire","mensuel" ou "annuel", respectivement). NOTE: pour générer des rapports hebdomadaires, mensuels ou annuels, au moins une planification de rapport quotidienne devra être disponible si vous nettoyer votre store DLF. Ce, parce que lorsqu'il ne peut trouver les données dans la base de donnée, Lire génère ces rapports par un algorithme de jonction dans lequel seuls les rapports quotidiens sont considérés.} ); # REFERENCE: lire.xml __( q{Fichier de configuration de rapport à utiliser.} ); # REFERENCE: lire.xml __( q{Les fichiers de configuration de rapport sont des fichiers texte avec une syntaxe particulière décrivant le type d'informations affichées dans le rapport ainsi que sa présentation. Lire est fourni avec un fichier-type de configuration pour chaque superservice mais vous pouvez créer le vôtre accordé à vos besoins.} ); # REFERENCE: lire.xml __( q{Configuration de rapport.} ); # REFERENCE: lire.xml __( q{Choisissez la configuration de rapport à utiliser pour cette planification.} ); # REFERENCE: lire.xml __( q{Sélectionner le superservice pour ce rapport.} ); # REFERENCE: lire.xml __( q{Lire assemble les données par "superservices", qui en gros sont des types de services. Cette option vous permet de sélectionner le type de données que ce report job devra traiter: web, base de données, email ou n'importe quel type affiché dans cette liste.} ); # REFERENCE: lire.xml __( q{Configurations de rapport} ); # REFERENCE: lire.xml __( q{Liste d'objets ReportConfig utilisés par ce store.} ); # REFERENCE: lire.xml __( q{Configuration de rapport} ); # REFERENCE: lire.xml __( q{Défini un rapport qui peut être utilisé pendant le Report job. Un rapport contient une ou plusieurs sections.} ); # REFERENCE: lire.xml __( q{Identifiant du rapport} ); # REFERENCE: lire.xml __( q{Cet identifiant peut être utilisé comme référence à la configuration de ce rapport.} ); # REFERENCE: lire.xml __( q{Sections du rapport} ); # REFERENCE: lire.xml __( q{List des sections définies dans le rapport.} ); # REFERENCE: lire.xml __( q{Définition de la section} ); # REFERENCE: lire.xml __( q{Défini une section d'un rapport.} ); # REFERENCE: lire.xml __( q{Filtres de la section} ); # REFERENCE: lire.xml __( q{List des filtres qui seront appliqués à cette section.} ); # REFERENCE: lire.xml __( q{Contenu de la section} ); # REFERENCE: lire.xml __( q{Le diagramme et le sous-rapport qui seront inclus dans la section.} ); # REFERENCE: lire.xml __( q{Superservice de la section} ); # REFERENCE: lire.xml __( q{Les superservices couverts dans cette section.} ); # REFERENCE: lire.xml __( q{Titre de la section} ); # REFERENCE: lire.xml __( q{Le titre de la section qui apparaîtra dans le rapport généré.} ); # REFERENCE: lire.xml __( q{Titre du rapport} ); # REFERENCE: lire.xml __( q{Le titre qui apparaîtra dans le rapport.} ); # REFERENCE: lire.xml __( q{Path to the sendmail(1) program.} ); # REFERENCE: lire.xml __( q{Configuration des streams DLF} ); # REFERENCE: lire.xml __( q{Cette liste de configuration contient la configuration pour chaque stream DLF du store.} ); # REFERENCE: lire.xml __( q{Name of the tai64nlocal(1) program.} ); # REFERENCE: lire.xml __( q{Certains fichiers de journaux, en particulier ceux produits par les programmes écrits par le professeur D. J. Bernstein, utilisent un format d'horodatage appelé "tai64n" qui représente les points dans le temps avec une précision à la nanoseconde selon la base de temps TAI. Ce programme est requis pour faire la conversion des secondes TAI en secondes UTC. Pour de plus amples informations, consultez le site web de DJB. La spécification du chemin au complet est facultative mais recommandée. Si vous ne traitez aucun fichier de journal en ce format (comme qmail ou djbdns), cette option n'est pas tenue en compte.} ); # REFERENCE: lire.xml __( q{Path to the tar(1) program.} ); # REFERENCE: lire.xml __( q{Chemin d'accès au fichier "unicode.tex"} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: lire.xml __( q{Obsolete} ); # REFERENCE: ct_dist.xml __( q{Distribution curve} ); # REFERENCE: ct_dist.xml __( q{Défini sur une courbe B-spline sera tracée par dessus le diagramme.} ); # REFERENCE: ct_dist.xml __( q{Variable} ); # REFERENCE: ct_dist.xml __( q{Une variable numérique pour laquelle la distribution sera tracée pour les cas choisis pour "case_var".} ); # REFERENCE: ct_lines.xml __( q{Afficher les nombres} ); # REFERENCE: ct_lines.xml __( q{Afficher les nombres en Y à côté des points?} ); # REFERENCE: ct_lines.xml __( q{Variable numérique des X} ); # REFERENCE: ct_lines.xml __( q{Si vous indiquez une variable numérique, elle sera utilisée pour l'axe des X à la place de la variable "case_var".} ); # REFERENCE: ct_lines.xml __( q{First Y Variable} ); # REFERENCE: ct_lines.xml __( q{Choisissez la variable qui sera représentée par la composante Y des points.} ); # REFERENCE: ct_lines.xml __( q{Seconde variable en Y} ); # REFERENCE: ct_lines.xml __( q{Choisissez une deuxième variable à tracer.} ); # REFERENCE: ct_lines.xml __( q{Troisième variable en Y} ); # REFERENCE: ct_lines.xml __( q{Choisissez une troisième variable à tracer.} ); # REFERENCE: ct_lines.xml __( q{Fourth Y Variable} ); # REFERENCE: ct_lines.xml __( q{Choisissez une quatrième variable à tracer.} ); # REFERENCE: ct_pie.xml __( q{La variable des valeurs} ); # REFERENCE: ct_pie.xml __( q{La variable numérique qui sera utilisée pour déterminer les aires du diagramme.} ); # REFERENCE: ct_scat.xml __( q{Ligne de régression} ); # REFERENCE: ct_scat.xml __( q{Spécifie si une ligne de régression sera dessinée ou non.} ); # REFERENCE: ct_scat.xml __( q{Étiquetter les points} ); # REFERENCE: ct_scat.xml __( q{Défini si les points seront étiquettés ou non.} ); # REFERENCE: ct_scat.xml __( q{Composant des X} ); # REFERENCE: ct_scat.xml __( q{Choisissez la variable qui représentera les composants en X des points.} ); # REFERENCE: ct_scat.xml __( q{Composant des Y} ); # REFERENCE: ct_scat.xml __( q{Choisissez la variable qui sera représentée par la composante Y des points.} ); # REFERENCE: ct_stack.xml __( q{Aires} ); # REFERENCE: ct_stack.xml __( q{Dessine des aires empilées à la place de barres.} ); # REFERENCE: ct_stack.xml __( q{First Y Variable} ); # REFERENCE: ct_stack.xml __( q{Choisissez la variable représentée par le premier élément de la pile.} ); # REFERENCE: ct_stack.xml __( q{Seconde variable en Y} ); # REFERENCE: ct_stack.xml __( q{Choisissez la deuxième variable à empiler.} ); # REFERENCE: ct_stack.xml __( q{Troisième variable en Y} ); # REFERENCE: ct_stack.xml __( q{Choisissez la troisième variable à empiler.} ); # REFERENCE: ct_stack.xml __( q{Fourth Y Variable} ); # REFERENCE: ct_stack.xml __( q{Choisissez la quatrième variable à empiler.} ); # REFERENCE: ct_vbars.xml __( q{Afficher les nombres} ); # REFERENCE: ct_vbars.xml __( q{Afficher le nombre en Y au-dessus des barres?} ); # REFERENCE: ct_vbars.xml __( q{First Y Variable} ); # REFERENCE: ct_vbars.xml __( q{Choisissez la variable qui représente la hauteur de la première barre.} ); # REFERENCE: ct_vbars.xml __( q{Seconde variable en Y} ); # REFERENCE: ct_vbars.xml __( q{Choisissez optionnellement une variable qui représente la hauteur de la seconde barre.} ); # REFERENCE: of_html.xml __( q{Obsolete} ); # REFERENCE: of_html.xml __( q{Générer ce rapport sur une page unique} ); # REFERENCE: of_html.xml __( q{Si vous désirez voir apparaître votre rapport sur une seule page, activez cette option. Autrement un document à plusieurs pages sera généré.} ); # REFERENCE: of_html.xml __( q{Use XHTML 1.0 syntax} ); # REFERENCE: of_html.xml __( q{XHTML is the modern form of HTML. XHTML files are actually XML files with an HTML vocabulary. Since XHTML 1.0 is just a little bit more than HTML 4.01, the result displayed will not change considerably but certain people like to live on the bleeding edge...} ); # REFERENCE: of_txt.xml __( q{Encodage utilisé dans les rapports formattés.} ); # REFERENCE: of_txt.xml __( q{Utilisez ce paramètre au cas où vous désirez formatter vos rapports dans un encodage différent de celui utilisé par votre système.} ); # REFERENCE: schema:lire_import_stats __( q{DLF Schema for ImportJob and AnalysisJob Statistics} ); # REFERENCE: schema:lire_import_stats __( q{This Dlf schema is used to store ImportJob and AnalysisJob statistics.} ); # REFERENCE: schema:lire_import_stats __( q{Start Time} ); # REFERENCE: schema:lire_import_stats __( q{The time at which the job was started.} ); # REFERENCE: schema:lire_import_stats __( q{Processing Time} ); # REFERENCE: schema:lire_import_stats __( q{The duration of the job.} ); # REFERENCE: schema:lire_import_stats __( q{Job Name} ); # REFERENCE: schema:lire_import_stats __( q{The name of the job.} ); # REFERENCE: schema:lire_import_stats __( q{Job Id} ); # REFERENCE: schema:lire_import_stats __( q{The job id to which the stats relate to. This is the job name plus the timestamp of the start of the job. The job id makes it possible to distinguish between different run of the same scheduled import or analysis job. } ); # REFERENCE: schema:lire_import_stats __( q{Lines Read} ); # REFERENCE: schema:lire_import_stats __( q{Number of log lines processed during that job.} ); # REFERENCE: schema:lire_import_stats __( q{Dlf Created} ); # REFERENCE: schema:lire_import_stats __( q{Number of DLF records created during the job.} ); # REFERENCE: schema:lire_import_stats __( q{Ignored Lines} ); # REFERENCE: schema:lire_import_stats __( q{Number of lines ignored during that ImportJob.} ); # REFERENCE: schema:lire_import_stats __( q{Saved Lines} ); # REFERENCE: schema:lire_import_stats __( q{Number of lines saved for later processing during that ImportJob.} ); # REFERENCE: schema:lire_import_stats __( q{Errors} ); # REFERENCE: schema:lire_import_stats __( q{Number of errors encountered during that job.} ); # REFERENCE: schema:lire_import_log __( q{DLF Schema for ImportJob Logging} ); # REFERENCE: schema:lire_import_log __( q{This Dlf schema is used to store information related to importation and analysis jobs. It is this Dlf stream that will contains the lines that were marked for continuation, that were ignored or that had errors during an importation process. } ); # REFERENCE: schema:lire_import_log __( q{Timestamp} ); # REFERENCE: schema:lire_import_log __( q{The time at which that log line was processed.} ); # REFERENCE: schema:lire_import_log __( q{Job Name} ); # REFERENCE: schema:lire_import_log __( q{The name of the ImportJob to which that log line is related.} ); # REFERENCE: schema:lire_import_log __( q{Job Id} ); # REFERENCE: schema:lire_import_log __( q{The job id in which that line was processed. This is the job name plus the timestamp of the start of the job. } ); # REFERENCE: schema:lire_import_log __( q{Line Type} ); # REFERENCE: schema:lire_import_log __( q{A typecode that can be error for line which resulted in an error, continuation for lines marked for processing at a later time and ignored for lines that were ignored. } ); # REFERENCE: schema:lire_import_log __( q{Line Number} ); # REFERENCE: schema:lire_import_log __( q{The log line number.} ); # REFERENCE: schema:lire_import_log __( q{Log Line} ); # REFERENCE: schema:lire_import_log __( q{The content of the log line.} ); # REFERENCE: schema:lire_import_log __( q{Message} ); # REFERENCE: schema:lire_import_log __( q{An optional message logged by the converter.} ); lire-2.1.1/all/po/Makefile.am0000644000175000017500000000600111134341472012606 00000000000000# $Id: Makefile.am,v 1.21 2009/01/17 11:38:34 vanbaal Exp $ # $Source: /cvsroot/logreport/service/all/po/Makefile.am,v $ # Makefile for various po files. # See # http://www.iro.umontreal.ca/translation/HTML/index.html # for hints on how to start your own translation COPYRIGHT_HOLDER = Stichting LogReport Foundation MSGID_BUGS_ADDRESS = bugs@logreport.org CONFIG_SPEC_DIR = all/lib/config-spec CONFIG_SPEC = lire.xml CONFIG_SPEC_IN = lire.xml.in CONFIG_SPECS = \ $(wildcard $(top_srcdir)/all/lib/Lire/ChartTypes/*.xml) \ $(wildcard $(top_srcdir)/all/lib/Lire/OutputFormats/*.xml) SPECS = config_spec:$(top_builddir)/$(CONFIG_SPEC_DIR)/$(CONFIG_SPEC) \ $(addprefix config_spec:, $(CONFIG_SPECS)) TEXTDOMAIN = lire XML_POT_SRC = config-spec.pot.pl LINGUAS = fr nl TEMPLATES = $(TEXTDOMAIN).pot CATALOGS = $(addsuffix .po, $(LINGUAS)) MO_FILES = $(addsuffix .mo, $(LINGUAS)) POTFILES = $(shell (find $(srcdir)/.. -name '*.pm' -o -name '*.in' | xargs grep -l 'use Locale::TextDomain' | grep -v Makefile )) LR_SPEC2POT = $(top_builddir)/all/script/lr_spec2pot SUFFIXES = .po .mo .pot BUILT_SOURCES = $(TEMPLATES) $(MO_FILES) $(XML_POT_SRC) lire-xml-stamp EXTRA_DIST = $(CATALOGS) $(BUILT_SOURCES) MAINTAINERCLEANFILES = $(BUILT_SOURCES) lire-xml-stamp : $(top_builddir)/$(CONFIG_SPEC_DIR)/$(CONFIG_SPEC_IN) cd $(top_builddir)/all/lib/config-spec && make lire.xml touch $@ $(LR_SPEC2POT): $(top_srcdir)/all/script/lr_spec2pot.in cd $(top_builddir)/all/script && $(MAKE) lr_spec2pot $(XML_POT_SRC): $(CONFIG_SPECS) lire-xml-stamp @PERL@ -I$(top_srcdir)/all/lib $(LR_SPEC2POT) \ --cfgspecdir $(top_srcdir)/all/lib/config-spec \ --schemasdir $(top_srcdir)/all/schemas \ $(SPECS) schema:lire_import_stats schema:lire_import_log \ > $(XML_POT_SRC) || ( rm -f $(XML_POT_SRC); false) $(TEMPLATES): $(POTFILES) $(XML_POT_SRC) @echo Updating \'$@\' catalog template. $(XGETTEXT) --from-code=UTF-8 --sort-output --foreign-user \ --add-comments=REFERENCE: \ --copyright-holder="$(COPYRIGHT_HOLDER)" \ --msgid-bugs-address="$(MSGID_BUGS_ADDRESS)" \ --keyword='$$__' --keyword=__ --keyword=__x \ --keyword=__n:1,2 --keyword=__nx:1,2 --keyword=__xn:1,2 \ --keyword=N__ --language=Perl --output $@ $^ $(CATALOGS): $(TEMPLATES) @echo Updating \'$@\' catalog. @if test -f $@; then : ; else cp $< $@; fi $(MSGMERGE) -U $@ $< && touch $@ .po.mo: @echo Generating \'$@\'. $(MSGFMT) --check --statistics --verbose -o $@ $< install-data-local: @cd $(srcdir); \ targetdir='$(DESTDIR)$(LR_PERL5LIBDIR)/LocaleData'; \ languages='$(LINGUAS)'; \ for lang in $$languages; do \ mkdir -p "$$targetdir/$$lang/LC_MESSAGES" || exit 1; \ dest="$$targetdir/$$lang/LC_MESSAGES/$(TEXTDOMAIN).mo"; \ cat="$$lang.mo"; \ echo "Installing $$cat as $$dest"; \ cp -f $$cat $$dest && chmod 644 $$dest || exit 1; \ done uninstall-local: @cd $(srcdir); \ targetdir='$(DESTDIR)$(LR_PERL5LIBDIR)/LocaleData'; \ languages='$(LINGUAS)'; \ for lang in $$languages; do \ rm -f $$targetdir/$$lang/LC_MESSAGES/$(TEXTDOMAIN).mo; \ done lire-2.1.1/all/po/Makefile.in0000644000175000017500000003014711677606133012641 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # $Id: Makefile.am,v 1.21 2009/01/17 11:38:34 vanbaal Exp $ # $Source: /cvsroot/logreport/service/all/po/Makefile.am,v $ # Makefile for various po files. # See # http://www.iro.umontreal.ca/translation/HTML/index.html # for hints on how to start your own translation VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = all/po DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ COPYRIGHT_HOLDER = Stichting LogReport Foundation MSGID_BUGS_ADDRESS = bugs@logreport.org CONFIG_SPEC_DIR = all/lib/config-spec CONFIG_SPEC = lire.xml CONFIG_SPEC_IN = lire.xml.in CONFIG_SPECS = \ $(wildcard $(top_srcdir)/all/lib/Lire/ChartTypes/*.xml) \ $(wildcard $(top_srcdir)/all/lib/Lire/OutputFormats/*.xml) SPECS = config_spec:$(top_builddir)/$(CONFIG_SPEC_DIR)/$(CONFIG_SPEC) \ $(addprefix config_spec:, $(CONFIG_SPECS)) TEXTDOMAIN = lire XML_POT_SRC = config-spec.pot.pl LINGUAS = fr nl TEMPLATES = $(TEXTDOMAIN).pot CATALOGS = $(addsuffix .po, $(LINGUAS)) MO_FILES = $(addsuffix .mo, $(LINGUAS)) POTFILES = $(shell (find $(srcdir)/.. -name '*.pm' -o -name '*.in' | xargs grep -l 'use Locale::TextDomain' | grep -v Makefile )) LR_SPEC2POT = $(top_builddir)/all/script/lr_spec2pot SUFFIXES = .po .mo .pot BUILT_SOURCES = $(TEMPLATES) $(MO_FILES) $(XML_POT_SRC) lire-xml-stamp EXTRA_DIST = $(CATALOGS) $(BUILT_SOURCES) MAINTAINERCLEANFILES = $(BUILT_SOURCES) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .po .mo .pot $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/po/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/po/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local .MAKE: all check install install-am install-strip .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-local install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am uninstall uninstall-am uninstall-local lire-xml-stamp : $(top_builddir)/$(CONFIG_SPEC_DIR)/$(CONFIG_SPEC_IN) cd $(top_builddir)/all/lib/config-spec && make lire.xml touch $@ $(LR_SPEC2POT): $(top_srcdir)/all/script/lr_spec2pot.in cd $(top_builddir)/all/script && $(MAKE) lr_spec2pot $(XML_POT_SRC): $(CONFIG_SPECS) lire-xml-stamp @PERL@ -I$(top_srcdir)/all/lib $(LR_SPEC2POT) \ --cfgspecdir $(top_srcdir)/all/lib/config-spec \ --schemasdir $(top_srcdir)/all/schemas \ $(SPECS) schema:lire_import_stats schema:lire_import_log \ > $(XML_POT_SRC) || ( rm -f $(XML_POT_SRC); false) $(TEMPLATES): $(POTFILES) $(XML_POT_SRC) @echo Updating \'$@\' catalog template. $(XGETTEXT) --from-code=UTF-8 --sort-output --foreign-user \ --add-comments=REFERENCE: \ --copyright-holder="$(COPYRIGHT_HOLDER)" \ --msgid-bugs-address="$(MSGID_BUGS_ADDRESS)" \ --keyword='$$__' --keyword=__ --keyword=__x \ --keyword=__n:1,2 --keyword=__nx:1,2 --keyword=__xn:1,2 \ --keyword=N__ --language=Perl --output $@ $^ $(CATALOGS): $(TEMPLATES) @echo Updating \'$@\' catalog. @if test -f $@; then : ; else cp $< $@; fi $(MSGMERGE) -U $@ $< && touch $@ .po.mo: @echo Generating \'$@\'. $(MSGFMT) --check --statistics --verbose -o $@ $< install-data-local: @cd $(srcdir); \ targetdir='$(DESTDIR)$(LR_PERL5LIBDIR)/LocaleData'; \ languages='$(LINGUAS)'; \ for lang in $$languages; do \ mkdir -p "$$targetdir/$$lang/LC_MESSAGES" || exit 1; \ dest="$$targetdir/$$lang/LC_MESSAGES/$(TEXTDOMAIN).mo"; \ cat="$$lang.mo"; \ echo "Installing $$cat as $$dest"; \ cp -f $$cat $$dest && chmod 644 $$dest || exit 1; \ done uninstall-local: @cd $(srcdir); \ targetdir='$(DESTDIR)$(LR_PERL5LIBDIR)/LocaleData'; \ languages='$(LINGUAS)'; \ for lang in $$languages; do \ rm -f $$targetdir/$$lang/LC_MESSAGES/$(TEXTDOMAIN).mo; \ done # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lire-2.1.1/all/etc/0000755000175000017500000000000011677607766011021 500000000000000lire-2.1.1/all/etc/explanation0000644000175000017500000000035510460672573013174 00000000000000This email contains a raw Lire report. You can format this report using the Lire software, available from LogReport at http://www.logreport.org/pub/. Instructions can be found in http://www.logreport.org/pub/current/README.lire-client. lire-2.1.1/all/etc/defaults.in0000644000175000017500000000776210460673253013073 00000000000000# vim: syntax=sh # $Id: defaults.in,v 1.134 2006/07/23 13:16:27 vanbaal Exp $ # # Copyright (C) 2000-2003 Stichting LogReport Foundation LogReport@LogReport.org # # This file is part of Lire. # # Lire is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program (see COPYING); if not, check with # http://www.gnu.org/copyleft/gpl.html. # # Replacement for test -nt which isn't supported # by Solaris' test (like if this was surprising...) lr_test_nt () { file1=$1 file2=$2 @PERL@ -e 'exit( (stat($ARGV[0]))[9] > (stat($ARGV[1]))[9] ? 0 : 1 )' $file1 $file2 } ######################################################################## # Runtime check for DocBook DTD # # Workaround for RH platforms where the path to DBK always change. # Anyway, this is really the proper way to locate XML DTDs. ######################################################################## runtime_docbook_dtd_check () { if test -z "$lr_dbk_xml_dtd" -o ! -f "$lr_dbk_xml_dtd" then if test -x "$xmlcatalog_path" -a -f /etc/xml/catalog then DTD=`$xmlcatalog_path /etc/xml/catalog "-//OASIS//DTD DocBook XML V4.1.2//EN" || true` if echo "$DTD" |grep '^file://' > /dev/null 2>/dev/null then lr_dbk_xml_dtd=`echo "$DTD" | sed -e 's|^file://||'` fi fi fi LR_DBK_XML_DTD="$lr_dbk_xml_dtd" } setup_archive_vars () { # LR_FAILEDDIR is used by lr_spool only LR_FAILEDDIR="$lr_archive_dir/email/raw/failed" export LR_FAILEDDIR } root_check () { if test -x /usr/xpg4/bin/id then # solaris' /usr/bin/id doesn't grok -u # don't you just love it... runid=/usr/xpg4/bin/id else runid=id fi if test -z "$lr_test_uid" then if test "`$runid -u`" -eq 0 -o "`$runid -ru`" -eq 0 then cat >&2 < superservice # empty lines and lines with a leading `#' are skipped # argomail email bind8_query dns bind9_query dns bind8_named dnszone cisco_ios firewall combined www common www dbmail msgstore exim email ## This DLF converter requires the Date::Manip perl module (available ## on CPAN). It also requires the use of the fw1-loggrabber helper ## application available from ## http://www.fellhauer-web.de/projects/fw1-loggrabber.html # fw1_lea firewall isdnlog dialup modgzip www ms_isa proxy mysql database nms email nmsmmp msgstore nmsstore msgstore pgsql database pix firewall postfix email qmail email referer www s1ms email sendmail email spamassassin spamfilter syslog syslog tinydns dns w3c_extended www welf firewall welf_proxy proxy xferlog ftp # lire-2.1.1/all/etc/Makefile.am0000644000175000017500000000242007745051035012752 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.20 2003/10/20 21:22:37 flacoste Exp $ ## Copyright (C) 2000-2001 Stichting LogReport Foundation LogReport@LogReport.org ## This file is part of Lire. ## ## Lire is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk alletcdir = $(sysconfdir)/$(PACKAGE) alletc_DATA = \ address.cf \ defaults \ disclaimer \ explanation \ profile_lean \ signature EXTRA_DIST = address.cf disclaimer explanation signature lire-2.1.1/all/etc/Makefile.in0000644000175000017500000003635611677606132013005 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/defaults.in $(srcdir)/profile_lean.in \ $(top_srcdir)/include/rules.mk subdir = all/etc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = defaults profile_lean CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(alletcdir)" DATA = $(alletc_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done alletcdir = $(sysconfdir)/$(PACKAGE) alletc_DATA = \ address.cf \ defaults \ disclaimer \ explanation \ profile_lean \ signature EXTRA_DIST = address.cf disclaimer explanation signature all: all-am .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/etc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/etc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): defaults: $(top_builddir)/config.status $(srcdir)/defaults.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ profile_lean: $(top_builddir)/config.status $(srcdir)/profile_lean.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-alletcDATA: $(alletc_DATA) @$(NORMAL_INSTALL) test -z "$(alletcdir)" || $(MKDIR_P) "$(DESTDIR)$(alletcdir)" @list='$(alletc_DATA)'; test -n "$(alletcdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(alletcdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(alletcdir)" || exit $$?; \ done uninstall-alletcDATA: @$(NORMAL_UNINSTALL) @list='$(alletc_DATA)'; test -n "$(alletcdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(alletcdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(alletcdir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(alletcdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-alletcDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-alletcDATA .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ distclean distclean-generic distdir dvi dvi-am html html-am \ info info-am install install-alletcDATA install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am uninstall uninstall-alletcDATA uninstall-am .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lire-2.1.1/all/etc/signature0000644000175000017500000000011110460672573012641 00000000000000 -- LogReport http://www.LogReport.org/ mailto:logreport@logreport.org lire-2.1.1/all/etc/profile_lean.in0000644000175000017500000000322710460673253013713 00000000000000# vim:syntax=sh # # $Id: profile_lean.in,v 1.14 2006/07/23 13:16:27 vanbaal Exp $ # # Copyright (C) 2000-2003 Stichting LogReport Foundation LogReport@LogReport.org # # This file is part of Lire. # # Lire is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program (see COPYING); if not, check with # http://www.gnu.org/copyleft/gpl.html. # # # profile_lean - set up lean and mean environment # if test -z "$LR_PROFILE_LEAN_INCLUDED" then # get newly created files mode -rw-r----- : we don't want to get # sensitive logdata worldreadable! umask 027 # dereference exec_prefix, for libexecdir and bindir dependency prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libexecdir@/@PACKAGE@ PATH=$libdir:$libdir/convertors:@bindir@:$PATH export PATH # Make sure perl can find our perl modules. perllibdirs="@LR_PERL5LIBDIR@" if test -z "$PERL5LIB" then PERL5LIB="$perllibdirs" else PERL5LIB="$perllibdirs:$PERL5LIB" fi export PERL5LIB LR_PROFILE_LEAN_INCLUDED=1 export LR_PROFILE_LEAN_INCLUDED fi # Local Variables: # mode: sh # End: lire-2.1.1/all/etc/disclaimer0000644000175000017500000000000110460672573012752 00000000000000 lire-2.1.1/all/lib/0000755000175000017500000000000011677607767011015 500000000000000lire-2.1.1/all/lib/xml/0000755000175000017500000000000011677607767011615 500000000000000lire-2.1.1/all/lib/xml/dtd/0000755000175000017500000000000011677607767012370 500000000000000lire-2.1.1/all/lib/xml/dtd/lrsml.dbx0000644000175000017500000014153711677605734014143 00000000000000
The Lire Report Specification Markup Language Document Type Definition for the Lire Report Specification Markup Language. This DTD defines a grammar that is used to specify reports that can be generated by Lire. Elements of this DTD uses the http://www.logreport.org/LRSML/ namespace that is usually mapped to the lire prefix. The latest version of that DTD is 2.1 and its public identifier is -//LogReport.ORG//DTD Lire Report Specification Markup Language V2.1//EN. Its canonical system identifier is http://www.logreport.org/LRSML/2.1/lrsml.dtd. <!-- --> <!-- Namespace prefix for validation using the DTD --> <!ENTITY % LIRE.xmlns.pfx "lire" > <!ENTITY % LIRE.pfx "%LIRE.xmlns.pfx;:" > <!ENTITY % LIRE.xmlns.attr.name "xmlns:%LIRE.xmlns.pfx;" > <!ENTITY % LIRE.xmlns.attr "%LIRE.xmlns.attr.name; CDATA #FIXED 'http://www.logreport.org/LRSML/'"> <!ENTITY % LRCML.xmlns.pfx "lrcml" > <!ENTITY % LRCML.pfx "%LRCML.xmlns.pfx;:" > <!ENTITY % LRCML.xmlns.attr.name "xmlns:%LRCML.xmlns.pfx;"> <!ENTITY % LRCML.xmlns.attr "%LRCML.xmlns.attr.name; CDATA #FIXED 'http://www.logreport.org/LRCML/'"> This DTD uses the common modules lire-types.mod which defines the data types recognized by Lire and lire-desc.mod which is used to include a subset of DocBook in description and text elements. <!ENTITY % lire-types.mod PUBLIC "-//LogReport.ORG//ENTITIES Lire Data Types V1.0//EN" "lire-types.mod"> %lire-types.mod; <!ENTITY % lire-desc.mod PUBLIC "-//LogReport.ORG//ELEMENTS Lire Description Elements V2.0//EN" "lire-desc.mod"> %lire-desc.mod; Each report specification is a XML document which has one report-spec as its root element. This DTD can also be used for filter specification which have one global-filter-spec as root element. <!ENTITY % LIRE.report-spec "%LIRE.pfx;report-spec" > <!ENTITY % LIRE.global-filter-spec "%LIRE.pfx;global-filter-spec"> <!ENTITY % LIRE.display-spec "%LIRE.pfx;display-spec" > <!ENTITY % LIRE.param-spec "%LIRE.pfx;param-spec" > <!ENTITY % LIRE.param "%LIRE.pfx;param" > <!ENTITY % LIRE.chart-configs "%LIRE.pfx;chart-configs" > <!ENTITY % LRCML.param "%LRCML.pfx;param" > <!ENTITY % LIRE.filter-spec "%LIRE.pfx;filter-spec" > <!ENTITY % LIRE.report-calc-spec "%LIRE.pfx;report-calc-spec" > <!ELEMENT %LRCML.param; (#PCDATA|%LRCML.param;)* > <!ATTLIST %LRCML.param; name NMTOKEN #REQUIRED value CDATA #IMPLIED >
<sgmltag>report-spec</sgmltag> element Root element of a report specification. It contains descriptive elements about the report specification (title, description). It contains the display elements that will be in the generated report (display-spec). It contains specification for the parameters that can be used to customize the report generated from this specification (param-spec). Finally, it contains elements to specify a filter expression which can be used to select a subset of the records (filter-spec) and the expression to build the report (report-calc-spec). <sgmltag>report-spec</sgmltag>'s attributes id the name of the superservice for which this report is available : i.e. email, www, dns, etc. schema The DLF schema used by the report. This defaults to the superservice's schema, but can be one of its derived or extended schema. joined-schemas A whitespace delimited list of additional schemas that will be joined for this report. This will make all fields define in these schemas available for the operators. The schemas that can be joined depends on the specification's schema. id An unique identifier for the report specification <!ELEMENT %LIRE.report-spec; (%LIRE.title;, %LIRE.description;, (%LIRE.param-spec;)?, %LIRE.display-spec;, (%LIRE.filter-spec;)?, (%LIRE.chart-configs;)?, %LIRE.report-calc-spec;) > <!ATTLIST %LIRE.report-spec; id ID #REQUIRED superservice %superservice.type; #REQUIRED schema NMTOKEN #IMPLIED joined-schemas NMTOKENS #IMPLIED %LIRE.xmlns.attr; %LRCML.xmlns.attr; >
<sgmltag>global-filter-spec</sgmltag> element Root element of a filter specification. It contains descriptive elements about the filter specification (title, description). It contains the display elements that will be used when that filter is used in a generated report (display-spec). It contains specification for the parameters that can be used to customize the filter generated from this specification (param-spec). Finally, it contains element to specify the filter expression which can be used to select a subset of the records (filter-spec). <sgmltag>global-filter-spec</sgmltag>'s attributes superservice the name of the superservice for which this filter is available : i.e. email, www, dns, etc. schema the DLF schema used by the report. This defaults to the superservice's schema, but can be one of its derived or extended schema. joined-schemas A whitespace delimited list of additional schemas that will be joined for this report. This will make all fields define in these schemas available for the operators. The schemas that can be joined depends on the specification's schema. id An unique identifier for the filter specification <!ELEMENT %LIRE.global-filter-spec; (%LIRE.title;, %LIRE.description;, (%LIRE.param-spec;)?, %LIRE.display-spec;, (%LIRE.filter-spec;)) > <!ATTLIST %LIRE.global-filter-spec; id ID #REQUIRED superservice %superservice.type; #REQUIRED schema NMTOKEN #IMPLIED joined-schemas NMTOKENS #IMPLIED %LIRE.xmlns.attr; >
<sgmltag>display-spec</sgmltag> element This element contains the descriptive element that will appear in the generated report. It contains one title and may contains one description which will be used as help message This element has no attribute. <!ELEMENT %LIRE.display-spec; (%LIRE.title;, (%LIRE.description;)?) >
<sgmltag>param-spec</sgmltag> element This element contains the parameters than can be customized in this report specification. This element doesn't have any attribute. <!ELEMENT %LIRE.param-spec; (%LIRE.param;)+ >
<sgmltag>param</sgmltag> element This element contains the specification for a parameter than can be used to customize this report. This element can contains a description element which can be used to explain the parameter's purpose. It is an error to define a parameter with the same name than one of the superservice's field. <sgmltag>param</sgmltag>'s attributes name the name of the parameter. type the parameter's data type default the parameter's default value <!ELEMENT %LIRE.param; (%LIRE.description;)? > <!ATTLIST %LIRE.param; name ID #REQUIRED type (%lire.types;) #REQUIRED default CDATA #IMPLIED >
<sgmltag>chart-configs</sgmltag> element This element contains one or more chart configurations that should be copied to the generated subreport. These chart configurations are specified using the Lire Report Configuration Markup Language. This element has no attribute. <!ELEMENT %LIRE.chart-configs; (%LRCML.param;)+ >
Filter expression elements <!ENTITY % LIRE.eq "%LIRE.pfx;eq" > <!ENTITY % LIRE.ne "%LIRE.pfx;ne" > <!ENTITY % LIRE.gt "%LIRE.pfx;gt" > <!ENTITY % LIRE.ge "%LIRE.pfx;ge" > <!ENTITY % LIRE.lt "%LIRE.pfx;lt" > <!ENTITY % LIRE.le "%LIRE.pfx;le" > <!ENTITY % LIRE.and "%LIRE.pfx;and" > <!ENTITY % LIRE.or "%LIRE.pfx;or" > <!ENTITY % LIRE.not "%LIRE.pfx;not" > <!ENTITY % LIRE.match "%LIRE.pfx;match" > <!ENTITY % LIRE.value "%LIRE.pfx;value" > <!ENTITY % expr "%LIRE.eq; | %LIRE.ne; | %LIRE.gt; | %LIRE.lt; | %LIRE.ge; | %LIRE.le; | %LIRE.and; | %LIRE.or; | %LIRE.not; | %LIRE.match; | %LIRE.value;" >
<sgmltag>filter-spec</sgmltag> element This element is used to select the subset of the records that will be used to generate the report. If this element is missing, all records will be used to generate the report. The content of this element are expression element which defines an expression which will evaluate to true or false for each record. The subset used for to generate the report are all records for which the expression evaluates to true. The value used to evaluate the expressions are either literal, value of parameter or value of one of the field of the record. Parameter and field starts with a $ followed by the name of the parameter or field. All other values are interpreted as literals. This element doesn't have any attribute. <!ELEMENT %LIRE.filter-spec; (%expr;) >
<sgmltag>value</sgmltag> element This expression element to false if the 'value' attribute is undefined, the empty string or 0. It evaluate to true otherwise. <sgmltag>value</sgmltag>'s attributes value The value that should be evaluated for a boolean context. <!ELEMENT %LIRE.value; EMPTY > <!ATTLIST %LIRE.value; value CDATA #REQUIRED >
<sgmltag>eq</sgmltag> element <!ELEMENT %LIRE.eq; EMPTY > <!ATTLIST %LIRE.eq; arg1 CDATA #REQUIRED arg2 CDATA #REQUIRED >
<sgmltag>ne</sgmltag> element <!ELEMENT %LIRE.ne; EMPTY > <!ATTLIST %LIRE.ne; arg1 CDATA #REQUIRED arg2 CDATA #REQUIRED >
<sgmltag>gt</sgmltag> element <!ELEMENT %LIRE.gt; EMPTY > <!ATTLIST %LIRE.gt; arg1 CDATA #REQUIRED arg2 CDATA #REQUIRED >
<sgmltag>ge</sgmltag> element <!ELEMENT %LIRE.ge; EMPTY > <!ATTLIST %LIRE.ge; arg1 CDATA #REQUIRED arg2 CDATA #REQUIRED >
<sgmltag>lt</sgmltag> element <!ELEMENT %LIRE.lt; EMPTY > <!ATTLIST %LIRE.lt; arg1 CDATA #REQUIRED arg2 CDATA #REQUIRED >
<sgmltag>le</sgmltag> element <!ELEMENT %LIRE.le; EMPTY > <!ATTLIST %LIRE.le; arg1 CDATA #REQUIRED arg2 CDATA #REQUIRED >
<sgmltag>match</sgmltag> element The match expression element tries to match a POSIX 1003.2 extended regular expression to a value and return true if there is a match and false otherwise. <sgmltag>match</sgmltag>'s attributes value the value which should matched re A POSIX 1003.2 extended regular expression. case-sensitive Is the regex sensitive to case. Defaults to true. <!ELEMENT %LIRE.match; EMPTY > <!ATTLIST %LIRE.match; value CDATA #REQUIRED re CDATA #REQUIRED case-sensitive (%bool.type;) 'true' >
<sgmltag>not</sgmltag> element <!ELEMENT %LIRE.not; (%expr;) >
<sgmltag>and</sgmltag> element <!ELEMENT %LIRE.and; (%expr;)+ >
<sgmltag>or</sgmltag> element <!ELEMENT %LIRE.or; (%expr;)+ >
Report Calculation Elements <!ENTITY % LIRE.timegroup "%LIRE.pfx;timegroup" > <!ENTITY % LIRE.group "%LIRE.pfx;group" > <!ENTITY % LIRE.rangegroup "%LIRE.pfx;rangegroup" > <!ENTITY % LIRE.timeslot "%LIRE.pfx;timeslot" > <!ENTITY % LIRE.field "%LIRE.pfx;field" > <!ENTITY % LIRE.sum "%LIRE.pfx;sum" > <!ENTITY % LIRE.avg "%LIRE.pfx;avg" > <!ENTITY % LIRE.min "%LIRE.pfx;min" > <!ENTITY % LIRE.max "%LIRE.pfx;max" > <!ENTITY % LIRE.first "%LIRE.pfx;first" > <!ENTITY % LIRE.last "%LIRE.pfx;last" > <!ENTITY % LIRE.count "%LIRE.pfx;count" > <!ENTITY % LIRE.records "%LIRE.pfx;records" > <!-- Empty group operator --> <!ENTITY % LIRE.empty-ops "%LIRE.sum; | %LIRE.avg; | %LIRE.count; | %LIRE.min; | %LIRE.max; | %LIRE.first; | %LIRE.last; | %LIRE.records;" > <!-- Group operations that are also aggregators --> <!ENTITY % LIRE.nestable-aggr "%LIRE.group; | %LIRE.timegroup; | %LIRE.timeslot; | %LIRE.rangegroup;" > <!-- Group operations --> <!ENTITY % LIRE.group-ops "%LIRE.empty-ops;| %LIRE.nestable-aggr;" > <!-- Containers for group operations --> <!ENTITY % LIRE.aggregator "%LIRE.nestable-aggr;" >
<sgmltag>report-calc-spec</sgmltag> element This element describes the computation needs to generate the report. It contains one aggregator element. This element doesn't have any attributes. <!ELEMENT %LIRE.report-calc-spec; (%LIRE.aggregator;) >
Common Attributes All elements which will create a column in the resulting report have a label attribute that will be used as the column label. When this attribute is omitted, the name attribute content will be used as column label. <!ENTITY % label.attr "label CDATA #IMPLIED"> All operation elements may have a name attribute which can be used to reference that column. (It is required in the case of aggrage functions). The primary usage is for controlling the sort order of the rows in the generated report. <!ENTITY % name.attr "name ID #IMPLIED"> <!ENTITY % name.attr.req "name ID #REQUIRED">
<sgmltag>group</sgmltag> element The group element generates a report where records are grouped by some field values and aggregate statistics are computed on those group of records. It contains the field that should be used for grouping and the statistics that should be computed. The sort order in the report is controlled by the 'sort' attribute. <sgmltag>group</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. If omitted a default name will be generated. sort whitespace delimited list of fields name that should used to sort the records. Field names can be prefixed by - to specify reverse sort order, otherwise ascending sort order is used. The name can also refer to the name attribute of the statistics element. limit limit the number of records that will be in the generated report. It can be either a positive integer or the name of a user supplied param. <!ELEMENT %LIRE.group; ((%LIRE.field;)+, (%LIRE.group-ops;)+) > <!ATTLIST %LIRE.group; %name.attr; sort NMTOKENS #IMPLIED limit CDATA #IMPLIED >
<sgmltag>timegroup</sgmltag> element The timegroup element generates a report where records are grouped by time range (hour, day, etc.). Statistics are then computed on these records grouped by period. <sgmltag>timegroup</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. If omitted a default name will be generated. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. field the name of the field which is used to group records. This should be a field which is of one of the time types (timestamp, date, time). It defaults to the default timestamp field if unspecified. period This is the timeperiod over which records should be grouped. Valid period looks like (hour, day, 1h, 30m, etc). It can also be the name of a user supplied param. <!ELEMENT %LIRE.timegroup; (%LIRE.group-ops;)+ > <!ATTLIST %LIRE.timegroup; %name.attr; %label.attr; field NMTOKEN #IMPLIED period CDATA #REQUIRED >
<sgmltag>timeslot</sgmltag> element The timeslot element generates a report where records are grouped according to a cyclic unit of time. The duration unit used won't fall over to the next higher unit. For example, this means that using a unit of 1d will generate a report where the stats will be by day of the week, 8h will generate a report by third of day, etc. The statistics are then computed over the records in the same timeslot. timeslot with 1d unit Using a specification like: <lire:timeslot unit="1d"> ... </lire:timeslot> would generate a report like: weekly overview Sunday ...Monday ...Tuesday ...... ...Saturday...
where data will be summed over all Sunday's, Monday's, ..., and Saturdays found in the log.
timeslot with 2m unit Specifying unit="2m" would generate a line for each two months, giving a yearly view. <sgmltag>timeslot</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. If omitted a default name will be generated. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. field the name of the field which is used to group records. This should be a field which is of one of the time types (timestamp, date, time). It defaults to the default 'timestamp' field if unspecified. unit This is the cyclic unit of time in which units the records are aggregated. It can be any duration value. (hour, day, 1h, 30m, etc). It can also be the name of a user supplied param. <!ELEMENT %LIRE.timeslot; (%LIRE.group-ops;)+ > <!ATTLIST %LIRE.timeslot; %name.attr; %label.attr; field NMTOKEN #IMPLIED unit CDATA #REQUIRED >
<sgmltag>rangroup</sgmltag> element The rangegroup element generates a report where records are grouped into distinct class delimited by a range. This element can be used to aggregates continuous numeric values like duration or bytes. Statistics are then computed on these records grouped in range class. <sgmltag>rangegroup</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. If omitted a default name will be generated. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. field the name of the field which is used to group records. This should be a field which is of a continuous numeric type (bytes, duration, int, number). Time types aggregation should use the timegroup element or timeslot. range-start The starting index of the first class. Defaults to 0. This won't be used a the lower limit of the class. It is only used to specify relatively at which values the classes delimitation start. For example, if the range-start is 1, and the range-size is 5, a class ranging -4 to 0 will be created if values are in that range. It can be supplied in any continuous unit (i.e 10k, 5m, etc.) This can also be the name of a user supplied param. range-size This is the size of class. It can be supplied in any continuous unit (i.e 10k, 5m, etc.) It can also be the name of a user supplied param. min-value All value lower then this boundary value will be considered to be equal to this value. If this parameter isn't set, the ranges won't be bounded on the left side. max-value All value greater then this boundary value will be considered to be equal to this value. If this parameter isn't set, the ranges won't be bounded on the right side. size-scale The rate at which the size scale from one class to another. If it is different then 1, this will create a logarithmic distribution. For example, setting this to 2, each successive class will be twice larger then the precedent : 0-9, 10-29, 30-69, etc. <!ELEMENT %LIRE.rangegroup; (%LIRE.group-ops;)+ > <!ATTLIST %LIRE.rangegroup; %name.attr; %label.attr; field NMTOKEN #REQUIRED range-start CDATA #IMPLIED range-size CDATA #REQUIRED min-value CDATA #IMPLIED max-value CDATA #IMPLIED size-scale CDATA #IMPLIED >
<sgmltag>field</sgmltag> element This element reference a DLF field which value will be displayed in a separate column in the resulting report. Its used to specify the grouping fields in the group element and to specify the fields to output in the records element. <sgmltag>field</sgmltag>'s attribute name The name of the DLF field that will be used as key for grouping. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. <!ELEMENT %LIRE.field; EMPTY > <!ATTLIST %LIRE.field; name NMTOKEN #REQUIRED %label.attr; >
<sgmltag>sum</sgmltag> element The sum element sums the value of a field in the group. <sgmltag>sum</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. field the field that should be summed. ratio This attribute can be used to display the sum as a ratio of the group or table total. If the attribute is set to group the resulting value will be the ratio on the group's total sum. If the attribute is set to table, it will be expressed as a ratio of the total sum of the table. The defaults is none which will not convert the sum to a ratio. weight This optional attribute can be used to create a weighted sum. It should contain a numerical DLF field name. The content of that field will be used to multiply each field value before summing them. <!ELEMENT %LIRE.sum; EMPTY > <!ATTLIST %LIRE.sum; %name.attr.req; %label.attr; ratio (none | group |table) 'none' field NMTOKEN #REQUIRED weight NMTOKEN #IMPLIED >
<sgmltag>avg</sgmltag> element The avg element calculate average of all value of a field in the group. The average will be computed either on the number of records if the by-field attribute is left empty, or by the number of different values that there are in the by-fields. <sgmltag>avg</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. field the field that should be averaged. If left unspecified the number of record will be counted. by-fields the fields that will be used to dermine the count over which the average is computed. weight This optional attribute can be used to create a weighted average. It should contain a numerical DLF field name. The content of that field will be used to multiply each field value before summing them. Its that weighted sum that will be used to calculate the average. <!ELEMENT %LIRE.avg; EMPTY > <!ATTLIST %LIRE.avg; %name.attr.req; %label.attr; field NMTOKEN #IMPLIED by-fields NMTOKENS #IMPLIED weight NMTOKEN #IMPLIED >
<sgmltag>max</sgmltag> element The max element calculates the maximum value for a field in all the group's records. <sgmltag>max</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. field the field for which the maximum value should found. <!ELEMENT %LIRE.max; EMPTY > <!ATTLIST %LIRE.max; %name.attr.req; %label.attr; field NMTOKEN #REQUIRED >
<sgmltag>min</sgmltag> element The min element calculates the minimum value for a field in all the group's records. <sgmltag>min</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. field the field for which the minimum value should found. <!ELEMENT %LIRE.min; EMPTY > <!ATTLIST %LIRE.min; %name.attr.req; %label.attr; field NMTOKEN #REQUIRED >
<sgmltag>first</sgmltag> element The first element will display the value of the value of one field of the first DLF record within its group. The sort order is controlled through the sort attribute.. <sgmltag>first</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. field the DLF field which will be displayed. sort whitespace delimited list of fields name that should used to sort the records. Field names can be prefixed by - to specify reverse sort order, otherwise ascending sort order is used. If this attribute is omitted, the records will be sort in ascending order of the default timestamp field. <!ELEMENT %LIRE.first; EMPTY > <!ATTLIST %LIRE.first; %name.attr.req; %label.attr; field NMTOKEN #REQUIRED sort NMTOKENS #IMPLIED >
<sgmltag>last</sgmltag> element The last element will display the value of the value of one field of the last DLF record within its group. The sort order is controlled through the sort attribute.. <sgmltag>last</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. field the DLF field which will be displayed. sort whitespace delimited list of fields name that should used to sort the records. Field names can be prefixed by - to specify reverse sort order, otherwise ascending sort order is used. If this attribute is omitted, the records will be sort in ascending order of the default timestamp field. <!ELEMENT %LIRE.last; EMPTY > <!ATTLIST %LIRE.last; %name.attr.req; %label.attr; field NMTOKEN #REQUIRED sort NMTOKENS #IMPLIED >
<sgmltag>count</sgmltag> element The count element counts the number of records in the group if the fields attribute is left empty. Otherwise, it will count the number of different values in the fields specified. <sgmltag>count</sgmltag>'s attributes name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. fields Which fields to count. If unspecified all records in the group are counted. If not, only different fields' value will be counted. ratio This attribute can be used to display the frequency as a ratio of the group or table total. If the attribute is set to group the resulting value will be the ratio on the group's total frequency. If the attribute is set to table, it will be expressed as a ratio of the total frequency of the table. The defaults is none which will not convert the frequency to a ratio. <!ELEMENT %LIRE.count; EMPTY > <!ATTLIST %LIRE.count; %name.attr.req; %label.attr; ratio (none | group |table) 'none' fields NMTOKENS #IMPLIED >
<sgmltag>records</sgmltag> element The records element will put the content of selected fields in the report. This can be used in reports that shows events matching certain criteria. The fields that will be included in the report for each record is specified by the field element. <sgmltag>records</sgmltag>'s attribute fields whitespace delimited list of fields name that should included in the report. <!ELEMENT %LIRE.records; EMPTY > <!ATTLIST %LIRE.records; fields NMTOKENS #REQUIRED >
lire-2.1.1/all/lib/xml/dtd/lrsml.dtd0000644000175000017500000003273011677605734014133 00000000000000 %lire-types.mod; %lire-desc.mod; lire-2.1.1/all/lib/xml/dtd/lrsml.xml0000644000175000017500000013012510460673260014141 00000000000000 label Sets the column label that will be used for column generated by this element. If omitted a default label will be generated. "> name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. If omitted a default name will be generated. "> name An identifier that can be used to reference this operation from other elements. This name will most often be used in the parent's sort attribute. "> ]>
Lire Report Specification Markup Language 2001-2004 Stichting LogReport Foundation $Revision: 1.14 $ $Date: 2006/07/23 13:16:32 $ $Author: vanbaal $ Copyright (C) 2001—2004 Stichting LogReport Foundation LogReport@LogReport.org This document is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. LRSML &lrsml-version;
The Lire Report Specification Markup Language Document Type Definition for the Lire Report Specification Markup Language. This DTD defines a grammar that is used to specify reports that can be generated by Lire. Elements of this DTD uses the http://www.logreport.org/LRSML/ namespace that is usually mapped to the lire prefix. The latest version of that DTD is &lrsml-version; and its public identifier is -//LogReport.ORG//DTD Lire Report Specification Markup Language V&lrsml-version;//EN. Its canonical system identifier is http://www.logreport.org/LRSML/&lrsml-version;/lrsml.dtd. ]]> This DTD uses the common modules lire-types.mod which defines the data types recognized by Lire and lire-desc.mod which is used to include a subset of DocBook in description and text elements. %lire-types.mod; %lire-desc.mod; ]]> Each report specification is a XML document which has one report-spec as its root element. This DTD can also be used for filter specification which have one global-filter-spec as root element. ]]>
<sgmltag>report-spec</sgmltag> element Root element of a report specification. It contains descriptive elements about the report specification (title, description). It contains the display elements that will be in the generated report (display-spec). It contains specification for the parameters that can be used to customize the report generated from this specification (param-spec). Finally, it contains elements to specify a filter expression which can be used to select a subset of the records (filter-spec) and the expression to build the report (report-calc-spec). <sgmltag>report-spec</sgmltag>'s attributes id the name of the superservice for which this report is available : i.e. email, www, dns, etc. schema The DLF schema used by the report. This defaults to the superservice's schema, but can be one of its derived or extended schema. joined-schemas A whitespace delimited list of additional schemas that will be joined for this report. This will make all fields define in these schemas available for the operators. The schemas that can be joined depends on the specification's schema. id An unique identifier for the report specification ]]>
<sgmltag>global-filter-spec</sgmltag> element Root element of a filter specification. It contains descriptive elements about the filter specification (title, description). It contains the display elements that will be used when that filter is used in a generated report (display-spec). It contains specification for the parameters that can be used to customize the filter generated from this specification (param-spec). Finally, it contains element to specify the filter expression which can be used to select a subset of the records (filter-spec). <sgmltag>global-filter-spec</sgmltag>'s attributes superservice the name of the superservice for which this filter is available : i.e. email, www, dns, etc. schema the DLF schema used by the report. This defaults to the superservice's schema, but can be one of its derived or extended schema. joined-schemas A whitespace delimited list of additional schemas that will be joined for this report. This will make all fields define in these schemas available for the operators. The schemas that can be joined depends on the specification's schema. id An unique identifier for the filter specification ]]>
<sgmltag>display-spec</sgmltag> element This element contains the descriptive element that will appear in the generated report. It contains one title and may contains one description which will be used as help message This element has no attribute. ]]>
<sgmltag>param-spec</sgmltag> element This element contains the parameters than can be customized in this report specification. This element doesn't have any attribute. ]]>
<sgmltag>param</sgmltag> element This element contains the specification for a parameter than can be used to customize this report. This element can contains a description element which can be used to explain the parameter's purpose. It is an error to define a parameter with the same name than one of the superservice's field. <sgmltag>param</sgmltag>'s attributes name the name of the parameter. type the parameter's data type default the parameter's default value ]]>
<sgmltag>chart-configs</sgmltag> element This element contains one or more chart configurations that should be copied to the generated subreport. These chart configurations are specified using the Lire Report Configuration Markup Language. This element has no attribute. ]]>
Filter expression elements ]]>
<sgmltag>filter-spec</sgmltag> element This element is used to select the subset of the records that will be used to generate the report. If this element is missing, all records will be used to generate the report. The content of this element are expression element which defines an expression which will evaluate to true or false for each record. The subset used for to generate the report are all records for which the expression evaluates to true. The value used to evaluate the expressions are either literal, value of parameter or value of one of the field of the record. Parameter and field starts with a $ followed by the name of the parameter or field. All other values are interpreted as literals. This element doesn't have any attribute. ]]>
<sgmltag>value</sgmltag> element This expression element to false if the 'value' attribute is undefined, the empty string or 0. It evaluate to true otherwise. <sgmltag>value</sgmltag>'s attributes value The value that should be evaluated for a boolean context. ]]>
<sgmltag>eq</sgmltag> element ]]>
<sgmltag>ne</sgmltag> element ]]>
<sgmltag>gt</sgmltag> element ]]>
<sgmltag>ge</sgmltag> element ]]>
<sgmltag>lt</sgmltag> element ]]>
<sgmltag>le</sgmltag> element ]]>
<sgmltag>match</sgmltag> element The match expression element tries to match a POSIX 1003.2 extended regular expression to a value and return true if there is a match and false otherwise. <sgmltag>match</sgmltag>'s attributes value the value which should matched re A POSIX 1003.2 extended regular expression. case-sensitive Is the regex sensitive to case. Defaults to true. ]]>
<sgmltag>not</sgmltag> element ]]>
<sgmltag>and</sgmltag> element ]]>
<sgmltag>or</sgmltag> element ]]>
Report Calculation Elements ]]>
<sgmltag>report-calc-spec</sgmltag> element This element describes the computation needs to generate the report. It contains one aggregator element. This element doesn't have any attributes. ]]>
Common Attributes All elements which will create a column in the resulting report have a label attribute that will be used as the column label. When this attribute is omitted, the name attribute content will be used as column label. ]]> All operation elements may have a name attribute which can be used to reference that column. (It is required in the case of aggrage functions). The primary usage is for controlling the sort order of the rows in the generated report. ]]>
<sgmltag>group</sgmltag> element The group element generates a report where records are grouped by some field values and aggregate statistics are computed on those group of records. It contains the field that should be used for grouping and the statistics that should be computed. The sort order in the report is controlled by the 'sort' attribute. <sgmltag>group</sgmltag>'s attributes &name.attr.desc; sort whitespace delimited list of fields name that should used to sort the records. Field names can be prefixed by - to specify reverse sort order, otherwise ascending sort order is used. The name can also refer to the name attribute of the statistics element. limit limit the number of records that will be in the generated report. It can be either a positive integer or the name of a user supplied param. ]]>
<sgmltag>timegroup</sgmltag> element The timegroup element generates a report where records are grouped by time range (hour, day, etc.). Statistics are then computed on these records grouped by period. <sgmltag>timegroup</sgmltag>'s attributes &name.attr.desc; &label.attr.desc; field the name of the field which is used to group records. This should be a field which is of one of the time types (timestamp, date, time). It defaults to the default timestamp field if unspecified. period This is the timeperiod over which records should be grouped. Valid period looks like (hour, day, 1h, 30m, etc). It can also be the name of a user supplied param. ]]>
<sgmltag>timeslot</sgmltag> element The timeslot element generates a report where records are grouped according to a cyclic unit of time. The duration unit used won't fall over to the next higher unit. For example, this means that using a unit of 1d will generate a report where the stats will be by day of the week, 8h will generate a report by third of day, etc. The statistics are then computed over the records in the same timeslot. timeslot with 1d unit Using a specification like: ... ]]> would generate a report like: weekly overview Sunday ...Monday ...Tuesday ...... ...Saturday...
where data will be summed over all Sunday's, Monday's, ..., and Saturdays found in the log.
timeslot with 2m unit Specifying unit="2m" would generate a line for each two months, giving a yearly view. <sgmltag>timeslot</sgmltag>'s attributes &name.attr.desc; &label.attr.desc; field the name of the field which is used to group records. This should be a field which is of one of the time types (timestamp, date, time). It defaults to the default 'timestamp' field if unspecified. unit This is the cyclic unit of time in which units the records are aggregated. It can be any duration value. (hour, day, 1h, 30m, etc). It can also be the name of a user supplied param. ]]>
<sgmltag>rangroup</sgmltag> element The rangegroup element generates a report where records are grouped into distinct class delimited by a range. This element can be used to aggregates continuous numeric values like duration or bytes. Statistics are then computed on these records grouped in range class. <sgmltag>rangegroup</sgmltag>'s attributes &name.attr.desc; &label.attr.desc; field the name of the field which is used to group records. This should be a field which is of a continuous numeric type (bytes, duration, int, number). Time types aggregation should use the timegroup element or timeslot. range-start The starting index of the first class. Defaults to 0. This won't be used a the lower limit of the class. It is only used to specify relatively at which values the classes delimitation start. For example, if the range-start is 1, and the range-size is 5, a class ranging -4 to 0 will be created if values are in that range. It can be supplied in any continuous unit (i.e 10k, 5m, etc.) This can also be the name of a user supplied param. range-size This is the size of class. It can be supplied in any continuous unit (i.e 10k, 5m, etc.) It can also be the name of a user supplied param. min-value All value lower then this boundary value will be considered to be equal to this value. If this parameter isn't set, the ranges won't be bounded on the left side. max-value All value greater then this boundary value will be considered to be equal to this value. If this parameter isn't set, the ranges won't be bounded on the right side. size-scale The rate at which the size scale from one class to another. If it is different then 1, this will create a logarithmic distribution. For example, setting this to 2, each successive class will be twice larger then the precedent : 0-9, 10-29, 30-69, etc. ]]>
<sgmltag>field</sgmltag> element This element reference a DLF field which value will be displayed in a separate column in the resulting report. Its used to specify the grouping fields in the group element and to specify the fields to output in the records element. <sgmltag>field</sgmltag>'s attribute name The name of the DLF field that will be used as key for grouping. &label.attr.desc; ]]>
<sgmltag>sum</sgmltag> element The sum element sums the value of a field in the group. <sgmltag>sum</sgmltag>'s attributes &name.attr.req.desc; &label.attr.desc; field the field that should be summed. ratio This attribute can be used to display the sum as a ratio of the group or table total. If the attribute is set to group the resulting value will be the ratio on the group's total sum. If the attribute is set to table, it will be expressed as a ratio of the total sum of the table. The defaults is none which will not convert the sum to a ratio. weight This optional attribute can be used to create a weighted sum. It should contain a numerical DLF field name. The content of that field will be used to multiply each field value before summing them. ]]>
<sgmltag>avg</sgmltag> element The avg element calculate average of all value of a field in the group. The average will be computed either on the number of records if the by-field attribute is left empty, or by the number of different values that there are in the by-fields. <sgmltag>avg</sgmltag>'s attributes &name.attr.req.desc; &label.attr.desc; field the field that should be averaged. If left unspecified the number of record will be counted. by-fields the fields that will be used to dermine the count over which the average is computed. weight This optional attribute can be used to create a weighted average. It should contain a numerical DLF field name. The content of that field will be used to multiply each field value before summing them. Its that weighted sum that will be used to calculate the average. ]]>
<sgmltag>max</sgmltag> element The max element calculates the maximum value for a field in all the group's records. <sgmltag>max</sgmltag>'s attributes &name.attr.req.desc; &label.attr.desc; field the field for which the maximum value should found. ]]>
<sgmltag>min</sgmltag> element The min element calculates the minimum value for a field in all the group's records. <sgmltag>min</sgmltag>'s attributes &name.attr.req.desc; &label.attr.desc; field the field for which the minimum value should found. ]]>
<sgmltag>first</sgmltag> element The first element will display the value of the value of one field of the first DLF record within its group. The sort order is controlled through the sort attribute.. <sgmltag>first</sgmltag>'s attributes &name.attr.req.desc; &label.attr.desc; field the DLF field which will be displayed. sort whitespace delimited list of fields name that should used to sort the records. Field names can be prefixed by - to specify reverse sort order, otherwise ascending sort order is used. If this attribute is omitted, the records will be sort in ascending order of the default timestamp field. ]]>
<sgmltag>last</sgmltag> element The last element will display the value of the value of one field of the last DLF record within its group. The sort order is controlled through the sort attribute.. <sgmltag>last</sgmltag>'s attributes &name.attr.req.desc; &label.attr.desc; field the DLF field which will be displayed. sort whitespace delimited list of fields name that should used to sort the records. Field names can be prefixed by - to specify reverse sort order, otherwise ascending sort order is used. If this attribute is omitted, the records will be sort in ascending order of the default timestamp field. ]]>
<sgmltag>count</sgmltag> element The count element counts the number of records in the group if the fields attribute is left empty. Otherwise, it will count the number of different values in the fields specified. <sgmltag>count</sgmltag>'s attributes &name.attr.req.desc; &label.attr.desc; fields Which fields to count. If unspecified all records in the group are counted. If not, only different fields' value will be counted. ratio This attribute can be used to display the frequency as a ratio of the group or table total. If the attribute is set to group the resulting value will be the ratio on the group's total frequency. If the attribute is set to table, it will be expressed as a ratio of the total frequency of the table. The defaults is none which will not convert the frequency to a ratio. ]]>
<sgmltag>records</sgmltag> element The records element will put the content of selected fields in the report. This can be used in reports that shows events matching certain criteria. The fields that will be included in the report for each record is specified by the field element. <sgmltag>records</sgmltag>'s attribute fields whitespace delimited list of fields name that should included in the report. ]]>
lire-2.1.1/all/lib/xml/dtd/catalog.xml0000644000175000017500000000462410460672602014425 00000000000000 lire-2.1.1/all/lib/xml/dtd/lrml.dbx0000644000175000017500000007213711677605734013757 00000000000000
The Report Markup Language Document Type Definition for the XML Lire Report Markup Language as generated by lr_dlf2xml. Elements of that DTD are defined in the namespace http://www.logreport.org/LRML/ which will be usually mapped to the lire prefix. The latest version of that DTD is 2.1 and its public identifier is -//LogReport.ORG//DTD Report Markup Language V2.1//EN. Its canonical system identifier is http://www.logreport.org/LRML/2.1/lrml.dtd. <!-- Namespace prefix for validation using the DTD --> <!ENTITY % LIRE.xmlns.pfx "lire" > <!ENTITY % LIRE.pfx "%LIRE.xmlns.pfx;:" > <!ENTITY % LIRE.xmlns.attr.name "xmlns:%LIRE.xmlns.pfx;" > <!ENTITY % LIRE.xmlns.attr "%LIRE.xmlns.attr.name; CDATA #FIXED 'http://www.logreport.org/LRML/'"> <!ENTITY % LRCML.xmlns.pfx "lrcml" > <!ENTITY % LRCML.pfx "%LRCML.xmlns.pfx;:" > <!ENTITY % LRCML.xmlns.attr.name "xmlns:%LRCML.xmlns.pfx;" > <!ENTITY % LRCML.xmlns.attr "%LRCML.xmlns.attr.name; CDATA #FIXED 'http://www.logreport.org/LRCML/'"> This DTD uses the common modules lire-types.mod which defines the data types recognized by Lire and lire-desc.mod which is used to include a subset of DocBook in description and text elements. <!-- Include needed modules --> <!ENTITY % lire-types.mod PUBLIC "-//LogReport.ORG//ENTITIES Lire Data Types V1.0//EN" "lire-types.mod"> %lire-types.mod; <!ENTITY % lire-desc.mod PUBLIC "-//LogReport.ORG//ELEMENTS Lire Description Elements V3.0//EN" "lire-desc.mod"> %lire-desc.mod; Each report is an XML document of which the top-level element is the report element. The report's data is contained in subreport elements (these hold the results of each report specification that was used to generate the report). <!-- Parameter entities which defines qualified names of the elements --> <!ENTITY % LIRE.report "%LIRE.pfx;report" > <!ENTITY % LIRE.section "%LIRE.pfx;section" > <!ENTITY % LIRE.subreport "%LIRE.pfx;subreport" > <!ENTITY % LIRE.missing-subreport "%LIRE.pfx;missing-subreport" > <!ENTITY % LIRE.table "%LIRE.pfx;table" > <!ENTITY % LIRE.table-info "%LIRE.pfx;table-info" > <!ENTITY % LIRE.group-info "%LIRE.pfx;group-info" > <!ENTITY % LIRE.column-info "%LIRE.pfx;column-info" > <!ENTITY % LIRE.group-summary "%LIRE.pfx;group-summary" > <!ENTITY % LIRE.entry "%LIRE.pfx;entry" > <!ENTITY % LIRE.group "%LIRE.pfx;group" > <!ENTITY % LIRE.name "%LIRE.pfx;name" > <!ENTITY % LIRE.value "%LIRE.pfx;value" > <!ENTITY % LIRE.date "%LIRE.pfx;date" > <!ENTITY % LIRE.timespan "%LIRE.pfx;timespan" > <!ENTITY % LIRE.chart-configs "%LIRE.pfx;chart-configs" > <!ENTITY % LRCML.param "%LRCML.pfx;param" > <!ELEMENT %LRCML.param; (#PCDATA|%LRCML.param;)* > <!ATTLIST %LRCML.param; name NMTOKEN #REQUIRED value CDATA #IMPLIED >
<sgmltag>report</sgmltag> element A report starts with the report's meta-informations: title, timespan and description. The report's actual data is contained in one or more subreports. <sgmltag>report</sgmltag>'s attributes version The version of the DTD to which this report complies. New report should use the 2.1 value. <!ELEMENT %LIRE.report; ((%LIRE.title;)?, (%LIRE.date;)?, (%LIRE.timespan;)?, (%LIRE.description;)?, (%LIRE.section;)+) > <!ATTLIST %LIRE.report; version %number.type; #REQUIRED %LIRE.xmlns.attr; %LRCML.xmlns.attr; >
Meta-information elements
<sgmltag>date</sgmltag> element The date element contains the date on which the report was generated. The content of this element should be the timestamp in a format suitable for display. <sgmltag/>'s attribute time The date in epoch time. <!ELEMENT %LIRE.date; (#PCDATA) > <!ATTLIST %LIRE.date; time %number.type; #REQUIRED>
<sgmltag>timespan</sgmltag> element The timespan element contains the starting and ending date which delimits the period of the report. The content of this element should be formatted for display purpose. The starting and ending time of the timespan can be read in epoch time in the attributes. The period attribute contains the timespan period. <sgmltag>timespan</sgmltag>'s attributes period Optional attribute which contains the period for which the report was generated. start The start time of the timespan in epoch time. end The end time of the timespan in epoch time. <!ELEMENT %LIRE.timespan; (#PCDATA) > <!ATTLIST %LIRE.timespan; period (hourly|daily|weekly|monthly|yearly) #IMPLIED start %number.type; #REQUIRED end %number.type; #REQUIRED >
<sgmltag>section</sgmltag> element The section element group common subreports together. The section's description will usually contains informations about the filters that were applied in this section. It contains a title, a description if some global filters were applied and the section's subreports. This element doesn't have any attribute. <!ELEMENT %LIRE.section; ( %LIRE.title;, (%LIRE.description;)?, (%LIRE.subreport;|%LIRE.missing-subreport;)*) >
<sgmltag>subreport</sgmltag> element The subreport element contains data for a certain report. It can contains meta-information elements, it they are different from the one of the report. Example of subreports for the email superservice are : Message delay by relay in seconds. Per hour traffic summary. Top 10 messages delivery. etc. The data is contains in a table element. If charts should be generated from the table's data, their configuration is contained in the chart-configs element. <sgmltag>subreport</sgmltag>'s attributes id A unique identifier that can be used to link to this element. superservice the name of the superservice from which the report's data comes from : i.e. email, www, dns, etc. type This is the name of the report specification that was used to generated this subreport. schemas A space delimited list of the schemas used by this subreport. <!ELEMENT %LIRE.subreport; ( %LIRE.title;, (%LIRE.description;)?, %LIRE.table;, (%LIRE.chart-configs;)?) > <!ATTLIST %LIRE.subreport; id ID #REQUIRED superservice %superservice.type; #REQUIRED type CDATA #REQUIRED schemas NMTOKENS #REQUIRED >
<sgmltag>missing-subreport</sgmltag> element <sgmltag>missing-subreport</sgmltag>'s attributes id A unique identifier that can be used to link to this element. superservice the name of the superservice from which the report's data comes from : i.e. email, www, dns, etc. type This is the name of the report specification that was used to generated this subreport. schemas A space delimited list of the schemas used by this subreport. reason The reason why this subreport is missing. <!ELEMENT %LIRE.missing-subreport; (EMPTY) > <!ATTLIST %LIRE.missing-subreport; id ID #IMPLIED superservice %superservice.type; #REQUIRED reason CDATA #IMPLIED type CDATA #REQUIRED schemas NMTOKENS #REQUIRED >
<sgmltag>table</sgmltag> element The table element contains the data of the subreport. It starts by a table-info element which contains information on the columns defined in the subreport. Following the table structure, there is a group-summary element which contains values computed over all the records. A table element can contains the subreport data directly or the data can be subdivided into groups. An example of a subreport which would contains directly the data would be "messages per to-domain, top-10". This would contains ten entries, one for each to-domain. An example of a subreport which would contains data in group would be "deliveries to users, per to-domain, top 30, top 5 users". It would contain 30 groups (one per to-domain) and each group would contain 5 entries (one per user). Group can be nested to arbitrary depth (but logic don't recommend to nest too much). <sgmltag>table</sgmltag>'s attributes show the number of entry to display. By default all entries should be displayed. <!ELEMENT %LIRE.table; (%LIRE.table-info;, %LIRE.group-summary;, (%LIRE.entry;)*) > <!ATTLIST %LIRE.table; show %int.type; #IMPLIED >
<sgmltag>table-info</sgmltag> element The table-info element contains information on the table structure. It contains one column-info element for each columns defined. It will also contains one group-info element for every grouping operation used in the report specification. This element doesn't have any attribute. <!ELEMENT %LIRE.table-info; (%LIRE.column-info;|%LIRE.group-info;)+ >
<sgmltag>group-info</sgmltag> element The group-info element play a similar role to the table-info element. Its used to group the columns defined by particular subgroup. <sgmltag>group-info</sgmltag>'s attribute name This attribute holds the name of the operation in the report specification which was responsible for the creation of this group data. row-idx Specify the row index of the table header in which this group's categorical labels should be displayed. <!ELEMENT %LIRE.group-info; (%LIRE.column-info;|%LIRE.group-info;)+ > <!ATTLIST %LIRE.group-info; name NMTOKEN #REQUIRED row-idx %int.type; #REQUIRED >
<sgmltag>column-info</sgmltag> element The column-info element describes a column of the table. It holds information related to display purpose (label, class, col-start, col-end, col-width) as well as information needed to use the content of the column as input to other computation (type, name). The col-start, col-end and col-width can be used to render the data in grid. <sgmltag>column-info</sgmltag>'s attributes name This attribute contains the name of the operation in the report specification which was used to generata data in this column. type The Lire data type of this column. class This attribute can either be categorical or numerical. Categorical data is held in name element and numerical data is held in value element. Also, numerical column will have column-summary element associated to them. label This optional attribute contains the column's label. If omitted, the name attribute's content will be used. col-start The column number in which this column start. The first column being column 0. col-end The column number in which this column ends. The first column being column 0. Spans are used to cover padding columns to indent grouped entries under their parent entry. col-width The suggested column width (in characters) to use for this column. max-chars The maximum entry's length in that column (this includes the label). avg-chars The average entry's length in that column (this includes the label). This value is rounded up to the nearest integer. <!ELEMENT %LIRE.column-info; EMPTY > <!ATTLIST %LIRE.column-info; name NMTOKEN #REQUIRED class (categorical|numerical) #REQUIRED type (%lire.types;) #REQUIRED label CDATA #IMPLIED col-start %int.type; #REQUIRED col-end %int.type; #REQUIRED col-width %int.type; #IMPLIED max-chars %int.type; #IMPLIED avg-chars %int.type; #IMPLIED >
<sgmltag>group-summary</sgmltag> element The group-summary contains one value element for all the columns that contains numerical data. These elements will contains the statistics computed over all the DLF records which were processed by the group or the subreport. <sgmltag>group-summary</sgmltag>'s attribute nrecords The number of DLF records that were processed by this group or subreport. missing-cases This attribute contains the number of LIRE_NOTAVAIL values found when computing the statistic. This number represents the number of records which didn't have the required information to group the records appropriately. If ommited or equals to 0, it means that all records had all the required information. row-idx Specify the row index in the table at which the group's summary value should be displayed. If this is attribute is omitted, the summary values won't be displayed. <!ELEMENT %LIRE.group-summary; (%LIRE.value;)* > <!ATTLIST %LIRE.group-summary; nrecords %int.type; #REQUIRED missing-cases %int.type; #IMPLIED row-idx %int.type; #IMPLIED >
<sgmltag>group</sgmltag> element The group element can be used to subdivide logically a report. It's used for aggregate reports like message per user per domain. It contains a group-summary element which contains the group's values for the whole group followed by the entries that makes the group. Groups can be nested more than once, but too much nesting augments information clutter and isn't useful for the user. <sgmltag>group</sgmltag>'s attributes id A unique identifier that can be used to link to this element. show the number of entry to display. By default all entries should be displayed. <!ELEMENT %LIRE.group; (%LIRE.group-summary;, (%LIRE.entry;)*)> <!ATTLIST %LIRE.group; id ID #IMPLIED show %int.type; #IMPLIED >
<sgmltag>entry</sgmltag> element The entry contains the data from the report. It is similar to a row in a table altough one entry may represents several rows when it includes nested groups. The name elements contain categorical items of data like user name, email, browser type, url. Note that numeric ranges (like time period for example) are also considered categorical data items. The value elements contain numericical data which are the result of a descriptive statistical operation: message count, bytes transferred, average delay, etc. <sgmltag>entry</sgmltag>'s attribute id A unique identifier that can be used to link to this element. row-idx Specify the row index in the table at which this entry's name and value elements should be rendered. If this is attribute is omitted, the entry won't be displayed. <!-- --> <!ELEMENT %LIRE.entry; (%LIRE.name;, (%LIRE.name;|%LIRE.value;|%LIRE.group;)+)> <!ATTLIST %LIRE.entry; id ID #IMPLIED row-idx %int.type; #IMPLIED >
<sgmltag>name</sgmltag> element The name elements contains categorical data column value. Its also used for numerical values that represents a class of values (like produced by the rangegroup or timegroup operations for example.) <sgmltag>name</sgmltag>'s attributes id A unique identifier that can be used to link to this element. col The column's name. It should be the same than the one in the corresponding column-info element. value When the displayed format is different from the DLF representation, this attribute contains the DLF representation. range In some cases (like in report generated by the timegroup, timeslot or rangegroup specification), this attribute will contains the range's length from the starting value which is in the 'value' attribute. <!ELEMENT %LIRE.name; (#PCDATA) > <!ATTLIST %LIRE.name; id ID #IMPLIED col NMTOKEN #REQUIRED value CDATA #IMPLIED range %number.type; #IMPLIED >
<sgmltag>value</sgmltag> element The value element contains numerical column value.. <sgmltag>value</sgmltag>'s attributes id A unique identifier that can be used to link to this element. col The column's name. It should be the same than the one in the corresponding column-info element. value contains the value in numeric format. This is used when the value was scaled (1k, 5M, etc.) total for average value, this contains the total used to compute the average. n for average value, this contains the n value that was used to compute the average. missing-cases This attribute contains the number of LIRE_NOTAVAIL values found when computing the statistic. When omitted, its assume to have a value of 0, i.e. that the value was defined in each DLF record. <!ELEMENT %LIRE.value; (#PCDATA) > <!ATTLIST %LIRE.value; id ID #IMPLIED col NMTOKEN #REQUIRED missing-cases %int.type; #IMPLIED value %number.type; #IMPLIED total %number.type; #IMPLIED n %number.type; #IMPLIED >
<sgmltag>chart-configs</sgmltag> element This element contains one or more chart configurations that should be generated from the table's. These chart configurations are specified using the Lire Report Configuration Markup Language. This element has no attribute. <!ELEMENT %LIRE.chart-configs; (%LRCML.param;)+ >
lire-2.1.1/all/lib/xml/dtd/lrml.dtd0000644000175000017500000001761411677605734013754 00000000000000 %lire-types.mod; %lire-desc.mod; lire-2.1.1/all/lib/xml/dtd/lrml.xml0000644000175000017500000007156010460672602013764 00000000000000 id A unique identifier that can be used to link to this element. "> ]>
Lire Report Markup Language 2001–2004 Stichting LogReport Foundation Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. LRML &lrml-version;
The Report Markup Language Document Type Definition for the XML Lire Report Markup Language as generated by lr_dlf2xml. Elements of that DTD are defined in the namespace http://www.logreport.org/LRML/ which will be usually mapped to the lire prefix. The latest version of that DTD is &lrml-version; and its public identifier is -//LogReport.ORG//DTD Report Markup Language V&lrml-version;//EN. Its canonical system identifier is http://www.logreport.org/LRML/&lrml-version;/lrml.dtd. ]]> This DTD uses the common modules lire-types.mod which defines the data types recognized by Lire and lire-desc.mod which is used to include a subset of DocBook in description and text elements. %lire-types.mod; %lire-desc.mod; ]]> Each report is an XML document of which the top-level element is the report element. The report's data is contained in subreport elements (these hold the results of each report specification that was used to generate the report). ]]>
<sgmltag>report</sgmltag> element A report starts with the report's meta-informations: title, timespan and description. The report's actual data is contained in one or more subreports. <sgmltag>report</sgmltag>'s attributes version The version of the DTD to which this report complies. New report should use the &lrml-version; value. ]]>
Meta-information elements
<sgmltag>date</sgmltag> element The date element contains the date on which the report was generated. The content of this element should be the timestamp in a format suitable for display. <sgmltag></sgmltag>'s attribute time The date in epoch time. ]]>
<sgmltag>timespan</sgmltag> element The timespan element contains the starting and ending date which delimits the period of the report. The content of this element should be formatted for display purpose. The starting and ending time of the timespan can be read in epoch time in the attributes. The period attribute contains the timespan period. <sgmltag>timespan</sgmltag>'s attributes period Optional attribute which contains the period for which the report was generated. start The start time of the timespan in epoch time. end The end time of the timespan in epoch time. ]]>
<sgmltag>section</sgmltag> element The section element group common subreports together. The section's description will usually contains informations about the filters that were applied in this section. It contains a title, a description if some global filters were applied and the section's subreports. This element doesn't have any attribute. ]]>
<sgmltag>subreport</sgmltag> element The subreport element contains data for a certain report. It can contains meta-information elements, it they are different from the one of the report. Example of subreports for the email superservice are : Message delay by relay in seconds. Per hour traffic summary. Top 10 messages delivery. etc. The data is contains in a table element. If charts should be generated from the table's data, their configuration is contained in the chart-configs element. <sgmltag>subreport</sgmltag>'s attributes &id.attr.desc; superservice the name of the superservice from which the report's data comes from : i.e. email, www, dns, etc. type This is the name of the report specification that was used to generated this subreport. schemas A space delimited list of the schemas used by this subreport. ]]>
<sgmltag>missing-subreport</sgmltag> element <sgmltag>missing-subreport</sgmltag>'s attributes &id.attr.desc; superservice the name of the superservice from which the report's data comes from : i.e. email, www, dns, etc. type This is the name of the report specification that was used to generated this subreport. schemas A space delimited list of the schemas used by this subreport. reason The reason why this subreport is missing. ]]>
<sgmltag>table</sgmltag> element The table element contains the data of the subreport. It starts by a table-info element which contains information on the columns defined in the subreport. Following the table structure, there is a group-summary element which contains values computed over all the records. A table element can contains the subreport data directly or the data can be subdivided into groups. An example of a subreport which would contains directly the data would be "messages per to-domain, top-10". This would contains ten entries, one for each to-domain. An example of a subreport which would contains data in group would be "deliveries to users, per to-domain, top 30, top 5 users". It would contain 30 groups (one per to-domain) and each group would contain 5 entries (one per user). Group can be nested to arbitrary depth (but logic don't recommend to nest too much). <sgmltag>table</sgmltag>'s attributes show the number of entry to display. By default all entries should be displayed. ]]>
<sgmltag>table-info</sgmltag> element The table-info element contains information on the table structure. It contains one column-info element for each columns defined. It will also contains one group-info element for every grouping operation used in the report specification. This element doesn't have any attribute. ]]>
<sgmltag>group-info</sgmltag> element The group-info element play a similar role to the table-info element. Its used to group the columns defined by particular subgroup. <sgmltag>group-info</sgmltag>'s attribute name This attribute holds the name of the operation in the report specification which was responsible for the creation of this group data. row-idx Specify the row index of the table header in which this group's categorical labels should be displayed. ]]>
<sgmltag>column-info</sgmltag> element The column-info element describes a column of the table. It holds information related to display purpose (label, class, col-start, col-end, col-width) as well as information needed to use the content of the column as input to other computation (type, name). The col-start, col-end and col-width can be used to render the data in grid. <sgmltag>column-info</sgmltag>'s attributes name This attribute contains the name of the operation in the report specification which was used to generata data in this column. type The Lire data type of this column. class This attribute can either be categorical or numerical. Categorical data is held in name element and numerical data is held in value element. Also, numerical column will have column-summary element associated to them. label This optional attribute contains the column's label. If omitted, the name attribute's content will be used. col-start The column number in which this column start. The first column being column 0. col-end The column number in which this column ends. The first column being column 0. Spans are used to cover padding columns to indent grouped entries under their parent entry. col-width The suggested column width (in characters) to use for this column. max-chars The maximum entry's length in that column (this includes the label). avg-chars The average entry's length in that column (this includes the label). This value is rounded up to the nearest integer. ]]>
<sgmltag>group-summary</sgmltag> element The group-summary contains one value element for all the columns that contains numerical data. These elements will contains the statistics computed over all the DLF records which were processed by the group or the subreport. <sgmltag>group-summary</sgmltag>'s attribute nrecords The number of DLF records that were processed by this group or subreport. missing-cases This attribute contains the number of LIRE_NOTAVAIL values found when computing the statistic. This number represents the number of records which didn't have the required information to group the records appropriately. If ommited or equals to 0, it means that all records had all the required information. row-idx Specify the row index in the table at which the group's summary value should be displayed. If this is attribute is omitted, the summary values won't be displayed. ]]>
<sgmltag>group</sgmltag> element The group element can be used to subdivide logically a report. It's used for aggregate reports like message per user per domain. It contains a group-summary element which contains the group's values for the whole group followed by the entries that makes the group. Groups can be nested more than once, but too much nesting augments information clutter and isn't useful for the user. <sgmltag>group</sgmltag>'s attributes &id.attr.desc; show the number of entry to display. By default all entries should be displayed. ]]>
<sgmltag>entry</sgmltag> element The entry contains the data from the report. It is similar to a row in a table altough one entry may represents several rows when it includes nested groups. The name elements contain categorical items of data like user name, email, browser type, url. Note that numeric ranges (like time period for example) are also considered categorical data items. The value elements contain numericical data which are the result of a descriptive statistical operation: message count, bytes transferred, average delay, etc. <sgmltag>entry</sgmltag>'s attribute &id.attr.desc; row-idx Specify the row index in the table at which this entry's name and value elements should be rendered. If this is attribute is omitted, the entry won't be displayed. ]]>
<sgmltag>name</sgmltag> element The name elements contains categorical data column value. Its also used for numerical values that represents a class of values (like produced by the rangegroup or timegroup operations for example.) <sgmltag>name</sgmltag>'s attributes &id.attr.desc; col The column's name. It should be the same than the one in the corresponding column-info element. value When the displayed format is different from the DLF representation, this attribute contains the DLF representation. range In some cases (like in report generated by the timegroup, timeslot or rangegroup specification), this attribute will contains the range's length from the starting value which is in the 'value' attribute. ]]>
<sgmltag>value</sgmltag> element The value element contains numerical column value.. <sgmltag>value</sgmltag>'s attributes &id.attr.desc; col The column's name. It should be the same than the one in the corresponding column-info element. value contains the value in numeric format. This is used when the value was scaled (1k, 5M, etc.) total for average value, this contains the total used to compute the average. n for average value, this contains the n value that was used to compute the average. missing-cases This attribute contains the number of LIRE_NOTAVAIL values found when computing the statistic. When omitted, its assume to have a value of 0, i.e. that the value was defined in each DLF record. ]]>
<sgmltag>chart-configs</sgmltag> element This element contains one or more chart configurations that should be generated from the table's. These chart configurations are specified using the Lire Report Configuration Markup Language. This element has no attribute. ]]>
lire-2.1.1/all/lib/xml/dtd/lire-desc-1.0.mod0000644000175000017500000000342010460672602015126 00000000000000 %DocBookDTD; lire-2.1.1/all/lib/xml/dtd/lrml-1.0.dtd0000644000175000017500000001373410460672602014232 00000000000000 %lire-types.mod; %lire-desc.mod; lire-2.1.1/all/lib/xml/dtd/Makefile.am0000644000175000017500000000445410003424324014313 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.13 2004/01/21 07:23:00 wsourdeau Exp $ ## Copyright (C) 2000-2001 Stichting LogReport Foundation LogReport@LogReport.org ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk BUILT_SOURCES = \ ldsml.dbx \ lrcml.dbx \ lrcsml.dbx \ lrsml.dbx \ lrml.dbx \ lire-desc.dbx \ lire-types.dbx \ $(LIRE_DTDS) LIRE_DTDS = \ ldsml.dtd \ lrcml.dtd \ lrcsml.dtd \ lrml.dtd \ lrsml.dtd \ lire-desc.mod \ lire-types.mod OLD_DTDS = lrml-1.0.dtd lrsml-1.0.dtd lire-desc-1.0.mod LIRE_CATALOGS = catalog catalog.xml XML_FILES = \ ldsml.xml \ lrcml.xml \ lrcsml.xml \ lrml.xml \ lrsml.xml \ lire-desc.xml \ lire-types.xml SUFFIXES = .xml .dbx .dtd .mod .xml.dbx: XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(top_srcdir)/all/lib/xml/stylesheet/xsl/make-dtddoc.xsl $< > $@ .xml.dtd: XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(top_srcdir)/all/lib/xml/stylesheet/xsl/make-dtd.xsl $< > $@ .xml.mod: XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(top_srcdir)/all/lib/xml/stylesheet/xsl/make-dtd.xsl $< > $@ alllibxmldtddir = $(datadir)/$(PACKAGE)/xml/dtd alllibxmldtd_DATA = $(LIRE_DTDS) $(LIRE_CATALOGS) $(OLD_DTDS) MAINTAINERCLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = $(LIRE_CATALOGS) $(BUILT_SOURCES) $(XML_FILES) $(OLD_DTDS) # Dummy depency because somehow GNU make wants to create a catalog.mod # from catalog.xml to produce catalog ??? catalog : catalog.xml @true lire-2.1.1/all/lib/xml/dtd/Makefile.in0000644000175000017500000004051011677606133014337 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/include/rules.mk subdir = all/lib/xml/dtd ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(alllibxmldtddir)" DATA = $(alllibxmldtd_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .xml .dbx .dtd .mod PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done BUILT_SOURCES = \ ldsml.dbx \ lrcml.dbx \ lrcsml.dbx \ lrsml.dbx \ lrml.dbx \ lire-desc.dbx \ lire-types.dbx \ $(LIRE_DTDS) LIRE_DTDS = \ ldsml.dtd \ lrcml.dtd \ lrcsml.dtd \ lrml.dtd \ lrsml.dtd \ lire-desc.mod \ lire-types.mod OLD_DTDS = lrml-1.0.dtd lrsml-1.0.dtd lire-desc-1.0.mod LIRE_CATALOGS = catalog catalog.xml XML_FILES = \ ldsml.xml \ lrcml.xml \ lrcsml.xml \ lrml.xml \ lrsml.xml \ lire-desc.xml \ lire-types.xml alllibxmldtddir = $(datadir)/$(PACKAGE)/xml/dtd alllibxmldtd_DATA = $(LIRE_DTDS) $(LIRE_CATALOGS) $(OLD_DTDS) MAINTAINERCLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = $(LIRE_CATALOGS) $(BUILT_SOURCES) $(XML_FILES) $(OLD_DTDS) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .xml .dbx .dtd .mod .1 .3pm .7 .dia .eps .in .pm .png .pod $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/xml/dtd/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/xml/dtd/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-alllibxmldtdDATA: $(alllibxmldtd_DATA) @$(NORMAL_INSTALL) test -z "$(alllibxmldtddir)" || $(MKDIR_P) "$(DESTDIR)$(alllibxmldtddir)" @list='$(alllibxmldtd_DATA)'; test -n "$(alllibxmldtddir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(alllibxmldtddir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(alllibxmldtddir)" || exit $$?; \ done uninstall-alllibxmldtdDATA: @$(NORMAL_UNINSTALL) @list='$(alllibxmldtd_DATA)'; test -n "$(alllibxmldtddir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(alllibxmldtddir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(alllibxmldtddir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(alllibxmldtddir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-alllibxmldtdDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-alllibxmldtdDATA .MAKE: all check check-am install install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ distclean distclean-generic distdir dvi dvi-am html html-am \ info info-am install install-alllibxmldtdDATA install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am uninstall uninstall-alllibxmldtdDATA \ uninstall-am .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi .xml.dbx: XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(top_srcdir)/all/lib/xml/stylesheet/xsl/make-dtddoc.xsl $< > $@ .xml.dtd: XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(top_srcdir)/all/lib/xml/stylesheet/xsl/make-dtd.xsl $< > $@ .xml.mod: XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(top_srcdir)/all/lib/xml/stylesheet/xsl/make-dtd.xsl $< > $@ # Dummy depency because somehow GNU make wants to create a catalog.mod # from catalog.xml to produce catalog ??? catalog : catalog.xml @true # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lire-2.1.1/all/lib/xml/dtd/lrsml-1.0.dtd0000644000175000017500000003037410460672602014414 00000000000000 %lire-types.mod; %lire-desc.mod; lire-2.1.1/all/lib/xml/dtd/ldsml.dbx0000644000175000017500000003265611677605734014126 00000000000000
The Lire DLF Schema Markup Language The Lire DLD Schema Markup Language (LDSML) is used describe the fields used by DLF records of a specific schema like www, email or msgstore. DLF schemas are defined in one XML document that should be installed in one of the directories that is included in the schema path (usually HOME/.lire/schemas and prefix/share/lire/schemas ). This document must conforms to the LDSML DTD which is described here. Elements of that DTD are defined in the namespace http://www.logreport.org/LDSML/ which will be usually mapped to the lire prefix (altough other prefixes may be used). The latest version of that DTD is 1.1 and its public identifier is -//LogReport.ORG//DTD Lire DLF Schema Markup Language V1.1//EN. Its canonical system identifier is http://www.logreport.org/LDSML/1.1/ldsml.dtd. <!-- Namespace prefix for validation using the DTD --> <!ENTITY % LIRE.xmlns.pfx "lire" > <!ENTITY % LIRE.pfx "%LIRE.xmlns.pfx;:" > <!ENTITY % LIRE.xmlns.attr.name "xmlns:%LIRE.xmlns.pfx;" > <!ENTITY % LIRE.xmlns.attr "%LIRE.xmlns.attr.name; CDATA #FIXED 'http://www.logreport.org/LDSML/'"> This DTD uses the common modules lire-types.mod which defines the data types recognized by Lire and lire-desc.mod which is used to include a subset of DocBook in description and text elements. <!ENTITY % lire-types.mod PUBLIC "-//LogReport.ORG//ENTITIES Lire Data Types V1.0//EN" "lire-types.mod"> %lire-types.mod; <!ENTITY % lire-desc.mod PUBLIC "-//LogReport.ORG//ELEMENTS Lire Description Elements V2.0//EN" "lire-desc.mod"> %lire-desc.mod; The top-level element in XML documents describing a DLF schema will be either a dlf-schema, extented-schema or derived-schema depending on the schema's type. DLF schemas are used as base schema for one superservice. For example, the DLF schema of the www superservice is named www. An extended schema is used to define additional fields which values are to be computed by an analyser. Extended schemas are named after the schema which they extend. For example, the www-attack extended schema adds an attack field which contains, if any, the attack that was attempted in that request. Derived schemas are used by another type of analysers which defines an entirely different schema. Whereas in the extended schema the new fields will be added to all the DLF records of the base schema, the derived schema will create new DLF records based on the DLF records of the base schema. An example of this is the www-session schema which computes users' session information based on the web requests contained in the www schema. Like for the extended-schema case, derived schemas are named after the base schema from which they are derived. The fields that makes each schema are defined using field elements. <!-- Prefixed names declaration. --> <!ENTITY % LIRE.dlf-schema "%LIRE.pfx;dlf-schema" > <!ENTITY % LIRE.extended-schema "%LIRE.pfx;extended-schema" > <!ENTITY % LIRE.derived-schema "%LIRE.pfx;derived-schema" > <!ENTITY % LIRE.field "%LIRE.pfx;field" >
The <sgmltag>dlf-schema</sgmltag> element The dlf-schema element is used to define the base schema of a superservice. It should contains optional title and description elements followed by field elements describing the schema structure. The title is an optional text string that will be used to in the automatic documentation generation that can be extracted from the schema definition. The description element should describe what is represented by each DLF records (one web request, one email delivery, one firewall event, etc.) <sgmltag>dlf-schema</sgmltag>'s attributes superservice This required attribute contains the name of the superservice described by this schema. This will also be used as the base schema's identifier. timestamp This required attribute contains the name of the field which contains the official event's timestamp. This field will be used to sort the DLF records for timegroup and timeslot report operations. <!ELEMENT %LIRE.dlf-schema; ( (%LIRE.title;)?, (%LIRE.description;)?, (%LIRE.field;)+ ) > <!ATTLIST %LIRE.dlf-schema; superservice %superservice.type; #REQUIRED timestamp IDREF #REQUIRED %LIRE.xmlns.attr; >
<sgmltag>extended-schema</sgmltag> element This is the root element of an extended DLF Schema. Extended-schema defines additional fields that will be added to the base schema. It contains an optional title, an optional description and one or more field specifications. <sgmltag>dlf-schema</sgmltag>'s attributes id This required attribute contains the identifier of that schema. This identifier should be composed of the superservice's name followed by an hypen (-) and then an word describing the extended schema. base-schema This required attribute contains the identifier of the schema that is extended. required-fields This optional attribute contains a space delimited list of field names that must be available in the base schema for the analyser to do its job. If any of the listed field is missing in the DLF, extended fields for the base schema cannot be computed. module This required attribute contains the name of the analyser that is used to compute the extended fields. This is a perl module that should be installed in perl's library path. <!ELEMENT %LIRE.extended-schema; ( (%LIRE.title;)?, (%LIRE.description;)?, (%LIRE.field;)+ ) > <!ATTLIST %LIRE.extended-schema; id NMTOKEN #REQUIRED base-schema NMTOKEN #REQUIRED module NMTOKEN #REQUIRED required-fields NMTOKENS #IMPLIED %LIRE.xmlns.attr; >
<sgmltag>derived-schema</sgmltag> element This is the root element of a derived DLF Schema. The difference between a normal schema and a derived schema is that the data is generated from another DLF instead of a log file. <sgmltag>derived-schema</sgmltag>'s attributes id This required attribute contains the identifier of that schema. This identifier should be composed of the superservice's name followed by an hypen (-) and then an word describing the derived schema. base-schema This required attribute contains the identifier of the schema from which this derived schema's data is derived. required-fields This optional attribute contains a space delimited list of field names that must be available in the base schema for the analyser to do its job. If any of the listed field is missing in the DLF, the derived records cannot be computed. module This required attribute contains the name of the analyser that is used to compute the derived records. This is a perl module that should be installed in perl's library path. timestamp This required attribute contains the name of the field which contains the official event's timestamp. This field will be used to sort the DLF records for timegroup and timeslot report operations. <!ELEMENT %LIRE.derived-schema; ( (%LIRE.title;)?, (%LIRE.description;)?, (%LIRE.field;)+ ) > <!ATTLIST %LIRE.derived-schema; id NMTOKEN #REQUIRED base-schema NMTOKEN #REQUIRED module NMTOKEN #REQUIRED required-fields NMTOKENS #IMPLIED timestamp IDREF #REQUIRED %LIRE.xmlns.attr; >
<sgmltag>field</sgmltag> element The field is used to describe the fields of the schema. Each field is specified by its name and type. The field element may contain an optional description element which gives more information on the data contained in the field. Description should be used to give better information to the DLF converter implementors on what should appears in that field. <sgmltag>field</sgmltag>'s attributes name This required attribute contains the name of the field. type This required attribute contains the the field's type. default This attribute is obsolete and will be removed in a future Lire release. label This optional attribute gives the label that should be used to display this field in reports. Defaults to the field's name when omitted. <!ELEMENT %LIRE.field; (%LIRE.description;)? > <!ATTLIST %LIRE.field; name ID #REQUIRED type (%lire.types;) #REQUIRED default CDATA #IMPLIED label CDATA #IMPLIED >
lire-2.1.1/all/lib/xml/dtd/ldsml.dtd0000644000175000017500000000745511677605734014123 00000000000000 %lire-types.mod; %lire-desc.mod; lire-2.1.1/all/lib/xml/dtd/ldsml.xml0000644000175000017500000003464510460672602014134 00000000000000 ]>
Lire DLF Schema Markup Language 2001-2002 Stichting LogReport Foundation Copyright (C) 2001,2002 Stichting LogReport Foundation LogReport@LogReport.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. LDSML &ldsml-version;
The Lire DLF Schema Markup Language The Lire DLD Schema Markup Language (LDSML) is used describe the fields used by DLF records of a specific schema like www, email or msgstore. DLF schemas are defined in one XML document that should be installed in one of the directories that is included in the schema path (usually HOME/.lire/schemas and prefix/share/lire/schemas ). This document must conforms to the LDSML DTD which is described here. Elements of that DTD are defined in the namespace http://www.logreport.org/LDSML/ which will be usually mapped to the lire prefix (altough other prefixes may be used). The latest version of that DTD is &ldsml-version; and its public identifier is -//LogReport.ORG//DTD Lire DLF Schema Markup Language V&ldsml-version;//EN. Its canonical system identifier is http://www.logreport.org/LDSML/&ldsml-version;/ldsml.dtd. ]]> This DTD uses the common modules lire-types.mod which defines the data types recognized by Lire and lire-desc.mod which is used to include a subset of DocBook in description and text elements. %lire-types.mod; %lire-desc.mod; ]]> The top-level element in XML documents describing a DLF schema will be either a dlf-schema, extented-schema or derived-schema depending on the schema's type. DLF schemas are used as base schema for one superservice. For example, the DLF schema of the www superservice is named www. An extended schema is used to define additional fields which values are to be computed by an analyser. Extended schemas are named after the schema which they extend. For example, the www-attack extended schema adds an attack field which contains, if any, the attack that was attempted in that request. Derived schemas are used by another type of analysers which defines an entirely different schema. Whereas in the extended schema the new fields will be added to all the DLF records of the base schema, the derived schema will create new DLF records based on the DLF records of the base schema. An example of this is the www-session schema which computes users' session information based on the web requests contained in the www schema. Like for the extended-schema case, derived schemas are named after the base schema from which they are derived. The fields that makes each schema are defined using field elements. ]]>
The <sgmltag>dlf-schema</sgmltag> element The dlf-schema element is used to define the base schema of a superservice. It should contains optional title and description elements followed by field elements describing the schema structure. The title is an optional text string that will be used to in the automatic documentation generation that can be extracted from the schema definition. The description element should describe what is represented by each DLF records (one web request, one email delivery, one firewall event, etc.) <sgmltag>dlf-schema</sgmltag>'s attributes superservice This required attribute contains the name of the superservice described by this schema. This will also be used as the base schema's identifier. timestamp This required attribute contains the name of the field which contains the official event's timestamp. This field will be used to sort the DLF records for timegroup and timeslot report operations. ]]>
<sgmltag>extended-schema</sgmltag> element This is the root element of an extended DLF Schema. Extended-schema defines additional fields that will be added to the base schema. It contains an optional title, an optional description and one or more field specifications. <sgmltag>dlf-schema</sgmltag>'s attributes id This required attribute contains the identifier of that schema. This identifier should be composed of the superservice's name followed by an hypen (-) and then an word describing the extended schema. base-schema This required attribute contains the identifier of the schema that is extended. required-fields This optional attribute contains a space delimited list of field names that must be available in the base schema for the analyser to do its job. If any of the listed field is missing in the DLF, extended fields for the base schema cannot be computed. module This required attribute contains the name of the analyser that is used to compute the extended fields. This is a perl module that should be installed in perl's library path. ]]>
<sgmltag>derived-schema</sgmltag> element This is the root element of a derived DLF Schema. The difference between a normal schema and a derived schema is that the data is generated from another DLF instead of a log file. <sgmltag>derived-schema</sgmltag>'s attributes id This required attribute contains the identifier of that schema. This identifier should be composed of the superservice's name followed by an hypen (-) and then an word describing the derived schema. base-schema This required attribute contains the identifier of the schema from which this derived schema's data is derived. required-fields This optional attribute contains a space delimited list of field names that must be available in the base schema for the analyser to do its job. If any of the listed field is missing in the DLF, the derived records cannot be computed. module This required attribute contains the name of the analyser that is used to compute the derived records. This is a perl module that should be installed in perl's library path. timestamp This required attribute contains the name of the field which contains the official event's timestamp. This field will be used to sort the DLF records for timegroup and timeslot report operations. ]]>
<sgmltag>field</sgmltag> element The field is used to describe the fields of the schema. Each field is specified by its name and type. The field element may contain an optional description element which gives more information on the data contained in the field. Description should be used to give better information to the DLF converter implementors on what should appears in that field. <sgmltag>field</sgmltag>'s attributes name This required attribute contains the name of the field. type This required attribute contains the the field's type. default This attribute is obsolete and will be removed in a future Lire release. label This optional attribute gives the label that should be used to display this field in reports. Defaults to the field's name when omitted. ]]>
lire-2.1.1/all/lib/xml/dtd/lrcml.dbx0000644000175000017500000001060511677605734014112 00000000000000
The Lire Report Configuration Markup Language Document Type Definition for the Lire Report Configuration Markup Language. This DTD defines a grammar that is used to store the Lire configuration. The configuration is stored in one or more XML files. Parameters set in later configuration files override the ones set in the formers. The valid parameter names as well as their description and type are specified using configuration specification documents. Elements of this DTD use the http://www.logreport.org/LRCML/ namespace, which is usually mapped to the lrcml prefix. The latest version of the DTD is 1.0 and its public identifier is -//LogReport.ORG//DTD Lire Report Specification Markup Language V1.0//EN. Its canonical system identifier is http://www.logreport.org/LRCML/1.0/lrcml.dtd. <!-- --> <!-- Namespace prefix for validation using the DTD --> <!ENTITY % LRCML.xmlns.pfx "lrcml" > <!ENTITY % xmlns.colon ":" > <!ENTITY % LRCML.pfx "%LRCML.xmlns.pfx;%xmlns.colon;" > <!ENTITY % LRCML.xmlns.attr.name "xmlns%xmlns.colon;%LRCML.xmlns.pfx;" > <!ENTITY % LRCML.xmlns.attr "%LRCML.xmlns.attr.name; CDATA #FIXED 'http://www.logreport.org/LRCML/'"> <!-- For the module which we are including --> <!ENTITY % LIRE.pfx "%LRCML.pfx;" > Each configuration specification is an XML document which has one config as its root element. <!ENTITY % LRCML.config "%LRCML.pfx;config" > <!ENTITY % LRCML.global "%LRCML.pfx;global" > <!ENTITY % LRCML.param "%LRCML.pfx;param" >
<sgmltag>config</sgmltag> element Root element of a configuration document. It contains presently only one global element which is used to hold the global configuration parameters. This element doesn't have any attributes. <!ELEMENT %LRCML.config; (%LRCML.global;) > <!ATTLIST %LRCML.config; %LRCML.xmlns.attr; >
<sgmltag>global</sgmltag> element This element starts the global configuration data. (This is the only scope currently defined). It contains a list of param elements. <!ELEMENT %LRCML.global; (%LRCML.param;)+ >
<sgmltag>param</sgmltag> element This element contains the parameter's value. The parameter's name is defined in the name attribute. The value attribute can be used to store scalar's value. When the parameter's type is a list, the values are stored in children param elements. This element has a mixed content type. We should probably use a value attribute to hold scalar values. <!ELEMENT %LRCML.param; (#PCDATA|%LRCML.param;)* > <!ATTLIST %LRCML.param; name NMTOKEN #REQUIRED value CDATA #IMPLIED >
lire-2.1.1/all/lib/xml/dtd/lrcml.dtd0000644000175000017500000000443611677605734014115 00000000000000 lire-2.1.1/all/lib/xml/dtd/lrcml.xml0000644000175000017500000001327010460673260014122 00000000000000 ]>
Lire Report Configuration Markup Language 2003 Stichting LogReport Foundation $Revision: 1.7 $ $Date: 2006/07/23 13:16:32 $ $Author: vanbaal $ Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This document is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. LRSML &lrcml-version;
The Lire Report Configuration Markup Language Document Type Definition for the Lire Report Configuration Markup Language. This DTD defines a grammar that is used to store the Lire configuration. The configuration is stored in one or more XML files. Parameters set in later configuration files override the ones set in the formers. The valid parameter names as well as their description and type are specified using configuration specification documents. Elements of this DTD use the http://www.logreport.org/LRCML/ namespace, which is usually mapped to the lrcml prefix. The latest version of the DTD is &lrcml-version; and its public identifier is -//LogReport.ORG//DTD Lire Report Specification Markup Language V&lrcml-version;//EN. Its canonical system identifier is http://www.logreport.org/LRCML/&lrcml-version;/lrcml.dtd. ]]> Each configuration specification is an XML document which has one config as its root element. ]]>
<sgmltag>config</sgmltag> element Root element of a configuration document. It contains presently only one global element which is used to hold the global configuration parameters. This element doesn't have any attributes. ]]>
<sgmltag>global</sgmltag> element This element starts the global configuration data. (This is the only scope currently defined). It contains a list of param elements. ]]>
<sgmltag>param</sgmltag> element This element contains the parameter's value. The parameter's name is defined in the name attribute. The value attribute can be used to store scalar's value. When the parameter's type is a list, the values are stored in children param elements. This element has a mixed content type. We should probably use a value attribute to hold scalar values. ]]>
lire-2.1.1/all/lib/xml/dtd/lire-types.dbx0000644000175000017500000002253011677605734015076 00000000000000
Lire Data Types Parameter Entities This module contains the parameter entity declarations for the data types used by all Lire DTDs. All defined data types have a <type>.type parameter entity which defines their type as an XML type valid in an attribute declaration and a <type>.name parameter entity that declare their name. Additionally, this module declares <name>.types parameter entities that group related types together. The latest version of that module is 1.0 and its public identifier is -//LogReport.ORG//ENTITIES Lire Data Types V1.0//EN.
Boolean Type The bool type. It contains a boolean value, either 0, 1, f, t, false or true. <!ENTITY % bool.type "0 | 1 | f | t | false | true | yes | no"> <!ENTITY % bool.name "bool" >
Integer Type The int type can contains positive or negative 32 bits integer. <!ENTITY % int.type "CDATA" > <!ENTITY % int.name "int" >
Number Type The number type can contains any number either integral or floating point. <!ENTITY % number.type "CDATA" > <!ENTITY % number.name "number" >
String Type The string type contains any displayable text string. <!ENTITY % string.type "CDATA" > <!ENTITY % string.name "string" >
Timestamp type The timestamp type contains a time representation which contains the date and time informations. It can be represented in UNIX epoch time. <!ENTITY % timestamp.type "CDATA" > <!ENTITY % timestamp.name "timestamp" >
Time Type The time type contains a time representation which contains only the time of the day, not the date. For example, this data type can represent 12h00, 15:13:10, etc. <!ENTITY % time.type "CDATA" > <!ENTITY % time.name "time" >
Date Type The date type contains a time representation which contains only a date. <!ENTITY % date.type "CDATA" > <!ENTITY % date.name "date" >
Duration Type The duration type contains a quantity of time. For example : 5s, 30h, 2days, 3w, 2M, 1y. (The authoritive list of supported duration types is coded in Lire::DataTypes::duration2sec.) <!ENTITY % duration.type "CDATA" > <!ENTITY % duration.name "duration" >
IP Type The ip type contains an IPv4 address. <!ENTITY % ip.type "CDATA" > <!ENTITY % ip.name "ip" >
Port Type The port type contains a port as used in the TCP to name the ends of logical connections. See also RFC 1700 and http://www.iana.org/numbers.htm. Commonly found in /etc/services on Unix systems. <!ENTITY % port.type "CDATA" > <!ENTITY % port.name "port" >
Hostname Type The hostname type contains an DNS hostname. (It can also contains the IPv4 address of the host). <!ENTITY % hostname.type "NMTOKEN" > <!ENTITY % hostname.name "hostname" >
URL Type The url type represents URL. <!ENTITY % url.type "CDATA" > <!ENTITY % url.name "url" >
Email Type The email type can be used to represent an email address. <!ENTITY % email.type "CDATA" > <!ENTITY % email.name "email" >
Bytes Type The bytes type can be used to represent quantity of data. (5m, 1.2g, 300bytes, etc.) <!ENTITY % bytes.type "CDATA" > <!ENTITY % bytes.name "bytes" >
Filename Type The filenametype can be used to Represent the name of a file or directory. <!ENTITY % filename.type "CDATA" > <!ENTITY % filename.name "filename" >
Field Type This type should be considered internal to Lire and shouldn't be used as a parameter or DLF field type. The field type can contains a DLF field name. It is used in the parameter specification to represent a choice of sort field for example. <!ENTITY % field.type "NMTOKEN" > <!ENTITY % field.name "field" >
Superservice Type This type should be considered internal to Lire and shouldn't be used as a parameter or DLF field type. <!ENTITY % superservice.type "NMTOKEN" > <!ENTITY % superservice.name "superservice" >
Related Types <!ENTITY % basic.types "%bool.name; | %int.name; | %number.name; | %string.name;" > <!ENTITY % internet.types "%email.name; | %url.name; | %ip.name; | %hostname.name; | %port.name;" > <!ENTITY % misc.types "%filename.name; | %bytes.name; " > <!ENTITY % time.types "%date.name; | %time.name; | %timestamp.name; | %duration.name;" > <!ENTITY % lire.types "%basic.types; | %time.types; | %internet.types; | %misc.types;" >
lire-2.1.1/all/lib/xml/dtd/lire-types.mod0000644000175000017500000000756711677605734015115 00000000000000 lire-2.1.1/all/lib/xml/dtd/lire-types.xml0000644000175000017500000002413010460673260015103 00000000000000 ]>
Lire Data Types 2001-2002 Stichting LogReport Foundation $Revision: 1.4 $ $Date: 2006/07/23 13:16:32 $ $Author: vanbaal $ Copyright (C) 2001,2002 Stichting LogReport Foundation LogReport@LogReport.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. lire-types &lire-types-version;
Lire Data Types Parameter Entities This module contains the parameter entity declarations for the data types used by all Lire DTDs. All defined data types have a <type>.type parameter entity which defines their type as an XML type valid in an attribute declaration and a <type>.name parameter entity that declare their name. Additionally, this module declares <name>.types parameter entities that group related types together. The latest version of that module is &lire-types-version; and its public identifier is -//LogReport.ORG//ENTITIES Lire Data Types V&lire-types-version;//EN.
Boolean Type The bool type. It contains a boolean value, either 0, 1, f, t, false or true. ]]>
Integer Type The int type can contains positive or negative 32 bits integer. ]]>
Number Type The number type can contains any number either integral or floating point. ]]>
String Type The string type contains any displayable text string. ]]>
Timestamp type The timestamp type contains a time representation which contains the date and time informations. It can be represented in UNIX epoch time. ]]>
Time Type The time type contains a time representation which contains only the time of the day, not the date. For example, this data type can represent 12h00, 15:13:10, etc. ]]>
Date Type The date type contains a time representation which contains only a date. ]]>
Duration Type The duration type contains a quantity of time. For example : 5s, 30h, 2days, 3w, 2M, 1y. (The authoritive list of supported duration types is coded in Lire::DataTypes::duration2sec.) ]]>
IP Type The ip type contains an IPv4 address. ]]>
Port Type The port type contains a port as used in the TCP to name the ends of logical connections. See also RFC 1700 and http://www.iana.org/numbers.htm. Commonly found in /etc/services on Unix systems. ]]>
Hostname Type The hostname type contains an DNS hostname. (It can also contains the IPv4 address of the host). ]]>
URL Type The url type represents URL. ]]>
Email Type The email type can be used to represent an email address. ]]>
Bytes Type The bytes type can be used to represent quantity of data. (5m, 1.2g, 300bytes, etc.) ]]>
Filename Type The filenametype can be used to Represent the name of a file or directory. ]]>
Field Type This type should be considered internal to Lire and shouldn't be used as a parameter or DLF field type. The field type can contains a DLF field name. It is used in the parameter specification to represent a choice of sort field for example. ]]>
Superservice Type This type should be considered internal to Lire and shouldn't be used as a parameter or DLF field type. ]]>
Related Types ]]>
lire-2.1.1/all/lib/xml/dtd/lrcsml.dbx0000644000175000017500000005302411677605734014277 00000000000000
The Lire Report Configuration Specification Markup Language Document Type Definition for the Lire Report Configuration Specification Markup Language. This DTD defines a grammar that is used to specify the configuration parameters used by the Lire framework. Besides the framework parameters, this DTD can be used by extensions writers to register their parameters with the framework. The configuration specifications are usually stored in prefix/share/lire/config-spec. Currently, Lire's configuration namespace is flat, which means that two different specification documents cannot define parameters of the same names. Elements of this DTD uses the http://www.logreport.org/LRCSML/ namespace that is usually mapped to the lrcsml prefix. The latest version of that DTD is 1.1 and its public identifier is -//LogReport.ORG//DTD Lire Report Specification Markup Language V1.1//EN. Its canonical system identifier is http://www.logreport.org/LRCSML/1.1/lrcsml.dtd. <!-- --> <!-- Namespace prefix for validation using the DTD --> <!ENTITY % LRCSML.xmlns.pfx "lrcsml" > <!ENTITY % LRCSML.pfx "%LRCSML.xmlns.pfx;:" > <!ENTITY % LRCSML.xmlns.attr.name "xmlns:%LRCSML.xmlns.pfx;" > <!ENTITY % LRCSML.xmlns.attr "%LRCSML.xmlns.attr.name; CDATA #FIXED 'http://www.logreport.org/LRCSML/'"> <!ENTITY % LRCML.xmlns.pfx "lrcml" > <!ENTITY % LRCML.pfx "%LRCML.xmlns.pfx;:" > <!ENTITY % LRCML.xmlns.attr.name "xmlns:%LRCML.xmlns.pfx;"> <!ENTITY % LRCML.xmlns.attr "%LRCML.xmlns.attr.name; CDATA #FIXED 'http://www.logreport.org/LRCML/'"> <!-- For the modules which we are including --> <!ENTITY % LIRE.pfx "%LRCSML.pfx;" > This DTD uses the common lire-desc.mod module which is used to include a subset of DocBook in description and text elements. <!ENTITY % lire-desc.mod PUBLIC "-//LogReport.ORG//ELEMENTS Lire Description Elements V2.0//EN" "lire-desc.mod"> %lire-desc.mod; Each configuration specification is a XML document which has one config-spec as its root element. <!ENTITY % LRCSML.config-spec "%LRCSML.pfx;config-spec" > <!ENTITY % LRCSML.summary "%LRCSML.pfx;summary" > <!ENTITY % LRCSML.boolean "%LRCSML.pfx;boolean" > <!ENTITY % LRCSML.integer "%LRCSML.pfx;integer" > <!ENTITY % LRCSML.string "%LRCSML.pfx;string" > <!ENTITY % LRCSML.dlf-schema "%LRCSML.pfx;dlf-schema" > <!ENTITY % LRCSML.dlf-streams "%LRCSML.pfx;dlf-streams" > <!ENTITY % LRCSML.dlf-converter "%LRCSML.pfx;dlf-converter" > <!ENTITY % LRCSML.command "%LRCSML.pfx;command" > <!ENTITY % LRCSML.file "%LRCSML.pfx;file" > <!ENTITY % LRCSML.executable "%LRCSML.pfx;executable" > <!ENTITY % LRCSML.directory "%LRCSML.pfx;directory" > <!ENTITY % LRCSML.select "%LRCSML.pfx;select" > <!ENTITY % LRCSML.option "%LRCSML.pfx;option" > <!ENTITY % LRCSML.list "%LRCSML.pfx;list" > <!ENTITY % LRCSML.object "%LRCSML.pfx;object" > <!ENTITY % LRCSML.output-format "%LRCSML.pfx;output-format" > <!ENTITY % LRCSML.plugin "%LRCSML.pfx;plugin" > <!ENTITY % LRCSML.record "%LRCSML.pfx;record" > <!ENTITY % LRCSML.reference "%LRCSML.pfx;reference" > <!ENTITY % LRCSML.report-config "%LRCSML.pfx;report-config" > <!ENTITY % LRCML.param "%LRCML.pfx;param" > <!ENTITY % LRCSML.summary "%LRCSML.pfx;summary" > <!ENTITY % types-spec "%LRCSML.boolean;|%LRCSML.integer;| %LRCSML.string;|%LRCSML.dlf-schema;| %LRCSML.dlf-converter;|%LRCSML.dlf-streams;| %LRCSML.command;|%LRCSML.file;| %LRCSML.executable;|%LRCSML.directory;| %LRCSML.select;|%LRCSML.list;|%LRCSML.object;| %LRCSML.output-format;| %LRCSML.plugin;|%LRCSML.record;|%LRCSML.reference; |%LRCSML.report-config; "> <!ENTITY % common.mix "(%LRCSML.summary;)?,(%LIRE.description;)?"> <!ENTITY % default "(%LRCML.param;)?" > <!ENTITY % common.mix.default "(%common.mix;, %default;)" > <!ELEMENT %LRCML.param; (#PCDATA|%LRCML.param;)* > <!ATTLIST %LRCML.param; name NMTOKEN #REQUIRED value CDATA #IMPLIED >
<sgmltag>config-spec</sgmltag> element Root element of a configuration specification document. It contains a list of parameter specifications.. This element doesn't have any attributes. <!ELEMENT %LRCSML.config-spec; ((%types-spec;)+) > <!ATTLIST %LRCSML.config-spec; %LRCSML.xmlns.attr; %LRCML.xmlns.attr; >
<sgmltag>summary</sgmltag> element This element is used for a short one description of the parameter's purpose. Use the description element for longer help text. This element doesn't have any attribute. <!ELEMENT %LRCSML.summary; (#PCDATA) >
Parameter Specifiations Elements
Common Attributes These attributes are common to all parameters specification elements: name Contains the name of the parameter to which this specification apply. required Determines if a valid value is required to make the container validates. Defaults to true. section This attribute can be used to set a menu section which can be used by configuration frontends to group parameters together. summary This attribute is equivalent to the summary element. obsolete This attribute can be used to mark a parameter as obsolete. Obsolete parameters will be removed from the specification in a future Lire release. <!ENTITY % common.attr " name NMTOKEN #REQUIRED required NMTOKEN '1' section CDATA #IMPLIED summary CDATA #IMPLIED obsolete NMTOKEN '0'">
<sgmltag>boolean</sgmltag> element This element is used to define a boolean parameter which can takes a yes or no value. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.boolean; (%common.mix.default;) > <!ATTLIST %LRCSML.boolean; %common.attr; >
<sgmltag>integer</sgmltag> element This element is used to define an integer parameter. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.integer; (%common.mix.default;) > <!ATTLIST %LRCSML.integer; %common.attr; >
<sgmltag>string</sgmltag> element This element is used to define an string parameter. These parameters can contains any value. This can have a valid-re attribute which specify a regular expression that the value must match. <!ELEMENT %LRCSML.string; (%common.mix.default;) > <!ATTLIST %LRCSML.string; %common.attr; valid-re CDATA #IMPLIED >
<sgmltag>dlf-converter</sgmltag> element This element is used to select a registered DlfConverter. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.dlf-converter; (%common.mix.default;) > <!ATTLIST %LRCSML.dlf-converter; %common.attr; >
<sgmltag>dlf-schema</sgmltag> element This element is used to select an available DlfSchema. If this element has the superservices set, only superservices can be selected. <!ELEMENT %LRCSML.dlf-schema; (%common.mix.default;) > <!ATTLIST %LRCSML.dlf-schema; %common.attr; superservices NMTOKEN '0' >
<sgmltag>dlf-streams</sgmltag> element This element is used to configure Lire::DlfStream in Lire::DlfStore. This element has no attribute. <!ELEMENT %LRCSML.dlf-streams; (%common.mix.default;) > <!ATTLIST %LRCSML.dlf-streams; %common.attr; >
<sgmltag>command</sgmltag> element This element is used to define a command parameter. To be accepted as valid the parameter's value must point to an executable file or an executable file with the specified value must exist in a directory of the PATH environment variable. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.command; (%common.mix.default;) > <!ATTLIST %LRCSML.command; %common.attr; >
<sgmltag>file</sgmltag> element This element is used to define a file parameter. To be accepted as valid, the parameter's value must point to an existing file. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.file; (%common.mix.default;) > <!ATTLIST %LRCSML.file; %common.attr; >
<sgmltag>directory</sgmltag> element This element is used to define a directory parameter. To be accepted as valid, the parameter's value must point to an existing directory. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.directory; (%common.mix.default;) > <!ATTLIST %LRCSML.directory; %common.attr; >
<sgmltag>executable</sgmltag> element This element is used to define an executable parameter. To be accepted as valid, the parameter's value must point to an existing executable file. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.executable; (%common.mix.default;) > <!ATTLIST %LRCSML.executable; %common.attr; >
<sgmltag>select</sgmltag> element This element is used to define a parameter for which the value is selected among a set of options. The allowed set of options is specified using option elements. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.select; (%common.mix;,(%LRCSML.option;)+, %default;) > <!ATTLIST %LRCSML.select; %common.attr; >
<sgmltag>option</sgmltag> element This element is used to define the valid values for a select parameter. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.option; (%common.mix;) > <!ATTLIST %LRCSML.option; %common.attr; >
<sgmltag>list</sgmltag> element This element is used to define a parameter that can contains an ordered set of values. The type of values which can be contained is specified using other parameters elements. Any number of parameters of the type specified by the children elements can be contained by the defined parameter. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.list; (%common.mix;,(%types-spec;)+,%default;) > <!ATTLIST %LRCSML.list; %common.attr; >
<sgmltag>object</sgmltag> element This element is used to define a parameter that will instantiate an object. The object will be instantiated by calling the "new_from_config()" class method defined in the package specified by the element's class attribute. The constructor will receive the hash instantiated from the parameter's components as parameter. The label attribute can be used to specify the contained element that should be used to represent this object in lists. <!ELEMENT %LRCSML.object; (%common.mix;,(%types-spec;)+,%default;) > <!ATTLIST %LRCSML.object; %common.attr; class NMTOKEN #REQUIRED label NMTOKEN #IMPLIED >
<sgmltag>output-format</sgmltag> element This element is used to select an available OutputFormat. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.output-format; (%common.mix.default;) > <!ATTLIST %LRCSML.output-format; %common.attr; >
<sgmltag>record</sgmltag> element This element is used to define a parameter that holds record-like data. The label attribute can be used to specify the contained element that should be used to represent this record in lists. <!ELEMENT %LRCSML.record; (%common.mix;,(%types-spec;)+, %default;) > <!ATTLIST %LRCSML.record; %common.attr; label NMTOKEN #IMPLIED >
<sgmltag>record</sgmltag> element This element is used to define a parameter that holds record-like data. The label attribute can be used to specify the contained element that should be used to represent this record in lists. <!ELEMENT %LRCSML.record; (%common.mix;,(%types-spec;)+,%default;) > <!ATTLIST %LRCSML.record; %common.attr; label NMTOKEN #IMPLIED >
<sgmltag>reference</sgmltag> element This element is used to select from an index. The index in which the available values is taken is specified in the index attribute. <!ELEMENT %LRCSML.reference; (%common.mix.default;) > <!ATTLIST %LRCSML.reference; %common.attr; index CDATA #REQUIRED >
<sgmltag>report-config</sgmltag> element This element is used to configure a report configuration. This element doesn't have any attribute. Each superservice can define a default report configuration using this element with a name of superservice_default. <!ELEMENT %LRCSML.report-config; (%common.mix.default;) > <!ATTLIST %LRCSML.report-config; %common.attr; >
<sgmltag>plugin</sgmltag> element This element is used to define a parameter for which the value is selected among a set of options. The allowed set of options is specified using option elements. The element will also contain additional parameters based on the selected value. The available paramaters should be defined in a record or similar specification named name_properties. For example, the additional parameters when the option_1 option is selected will be found in the specification named option_1_properties. This element doesn't have any specific attributes. <!ELEMENT %LRCSML.plugin; (%common.mix;,(%LRCSML.option;)+, %default;) > <!ATTLIST %LRCSML.plugin; %common.attr; >
lire-2.1.1/all/lib/xml/dtd/lrcsml.dtd0000644000175000017500000002307211677605734014275 00000000000000 %lire-desc.mod; lire-2.1.1/all/lib/xml/dtd/lrcsml.xml0000644000175000017500000005431310460673260014310 00000000000000 ]>
Lire Report Configuration Specification Markup Language 2003 Stichting LogReport Foundation $Revision: 1.20 $ $Date: 2006/07/23 13:16:32 $ $Author: vanbaal $ Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This document is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. LRCSML &lrcsml-version;
The Lire Report Configuration Specification Markup Language Document Type Definition for the Lire Report Configuration Specification Markup Language. This DTD defines a grammar that is used to specify the configuration parameters used by the Lire framework. Besides the framework parameters, this DTD can be used by extensions writers to register their parameters with the framework. The configuration specifications are usually stored in prefix/share/lire/config-spec. Currently, Lire's configuration namespace is flat, which means that two different specification documents cannot define parameters of the same names. Elements of this DTD uses the http://www.logreport.org/LRCSML/ namespace that is usually mapped to the lrcsml prefix. The latest version of that DTD is &lrcsml-version; and its public identifier is -//LogReport.ORG//DTD Lire Report Specification Markup Language V&lrcsml-version;//EN. Its canonical system identifier is http://www.logreport.org/LRCSML/&lrcsml-version;/lrcsml.dtd. ]]> This DTD uses the common lire-desc.mod module which is used to include a subset of DocBook in description and text elements. %lire-desc.mod; ]]> Each configuration specification is a XML document which has one config-spec as its root element. ]]>
<sgmltag>config-spec</sgmltag> element Root element of a configuration specification document. It contains a list of parameter specifications.. This element doesn't have any attributes. ]]>
<sgmltag>summary</sgmltag> element This element is used for a short one description of the parameter's purpose. Use the description element for longer help text. This element doesn't have any attribute. ]]>
Parameter Specifiations Elements
Common Attributes These attributes are common to all parameters specification elements: name Contains the name of the parameter to which this specification apply. required Determines if a valid value is required to make the container validates. Defaults to true. section This attribute can be used to set a menu section which can be used by configuration frontends to group parameters together. summary This attribute is equivalent to the summary element. obsolete This attribute can be used to mark a parameter as obsolete. Obsolete parameters will be removed from the specification in a future Lire release. ]]>
<sgmltag>boolean</sgmltag> element This element is used to define a boolean parameter which can takes a yes or no value. This element doesn't have any specific attributes. ]]>
<sgmltag>integer</sgmltag> element This element is used to define an integer parameter. This element doesn't have any specific attributes. ]]>
<sgmltag>string</sgmltag> element This element is used to define an string parameter. These parameters can contains any value. This can have a valid-re attribute which specify a regular expression that the value must match. ]]>
<sgmltag>dlf-converter</sgmltag> element This element is used to select a registered DlfConverter. This element doesn't have any specific attributes. ]]>
<sgmltag>dlf-schema</sgmltag> element This element is used to select an available DlfSchema. If this element has the superservices set, only superservices can be selected. ]]>
<sgmltag>dlf-streams</sgmltag> element This element is used to configure Lire::DlfStream in Lire::DlfStore. This element has no attribute. ]]>
<sgmltag>command</sgmltag> element This element is used to define a command parameter. To be accepted as valid the parameter's value must point to an executable file or an executable file with the specified value must exist in a directory of the PATH environment variable. This element doesn't have any specific attributes. ]]>
<sgmltag>file</sgmltag> element This element is used to define a file parameter. To be accepted as valid, the parameter's value must point to an existing file. This element doesn't have any specific attributes. ]]>
<sgmltag>directory</sgmltag> element This element is used to define a directory parameter. To be accepted as valid, the parameter's value must point to an existing directory. This element doesn't have any specific attributes. ]]>
<sgmltag>executable</sgmltag> element This element is used to define an executable parameter. To be accepted as valid, the parameter's value must point to an existing executable file. This element doesn't have any specific attributes. ]]>
<sgmltag>select</sgmltag> element This element is used to define a parameter for which the value is selected among a set of options. The allowed set of options is specified using option elements. This element doesn't have any specific attributes. ]]>
<sgmltag>option</sgmltag> element This element is used to define the valid values for a select parameter. This element doesn't have any specific attributes. ]]>
<sgmltag>list</sgmltag> element This element is used to define a parameter that can contains an ordered set of values. The type of values which can be contained is specified using other parameters elements. Any number of parameters of the type specified by the children elements can be contained by the defined parameter. This element doesn't have any specific attributes. ]]>
<sgmltag>object</sgmltag> element This element is used to define a parameter that will instantiate an object. The object will be instantiated by calling the "new_from_config()" class method defined in the package specified by the element's class attribute. The constructor will receive the hash instantiated from the parameter's components as parameter. The label attribute can be used to specify the contained element that should be used to represent this object in lists. ]]>
<sgmltag>output-format</sgmltag> element This element is used to select an available OutputFormat. This element doesn't have any specific attributes. ]]>
<sgmltag>record</sgmltag> element This element is used to define a parameter that holds record-like data. The label attribute can be used to specify the contained element that should be used to represent this record in lists. ]]>
<sgmltag>record</sgmltag> element This element is used to define a parameter that holds record-like data. The label attribute can be used to specify the contained element that should be used to represent this record in lists. ]]>
<sgmltag>reference</sgmltag> element This element is used to select from an index. The index in which the available values is taken is specified in the index attribute. ]]>
<sgmltag>report-config</sgmltag> element This element is used to configure a report configuration. This element doesn't have any attribute. Each superservice can define a default report configuration using this element with a name of superservice_default. ]]>
<sgmltag>plugin</sgmltag> element This element is used to define a parameter for which the value is selected among a set of options. The allowed set of options is specified using option elements. The element will also contain additional parameters based on the selected value. The available paramaters should be defined in a record or similar specification named name_properties. For example, the additional parameters when the option_1 option is selected will be found in the specification named option_1_properties. This element doesn't have any specific attributes. ]]>
lire-2.1.1/all/lib/xml/dtd/catalog0000644000175000017500000000354010460672602013622 00000000000000OVERRIDE YES PUBLIC "-//LogReport.ORG//DTD Lire DLF Schema Markup Language V1.0//EN" "ldsml.dtd" SYSTEM "http://www.logreport.org/LDSML/1.0/ldsml.dtd" "ldsml.dtd" PUBLIC "-//LogReport.ORG//DTD Lire DLF Schema Markup Language V1.1//EN" "ldsml.dtd" SYSTEM "http://www.logreport.org/LDSML/1.1/ldsml.dtd" "ldsml.dtd" PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V1.0//EN" "lrsml-1.0.dtd" SYSTEM "http://www.logreport.org/LRSML/1.0/lrsml.dtd" "lrsml-1.0.dtd" PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.0//EN" "lrsml.dtd" SYSTEM "http://www.logreport.org/LRSML/2.0/lrsml.dtd" "lrsml.dtd" PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.1//EN" "lrsml.dtd" SYSTEM "http://www.logreport.org/LRSML/2.1/lrsml.dtd" "lrsml.dtd" PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V1.0//EN" "lrml-1.0.dtd" SYSTEM "http://www.logreport.org/LRML/1.0/lire.dtd" "lrml-1.0.dtd" SYSTEM "http://www.logreport.org/LRML/1.0/lrml.dtd" "lrml-1.0.dtd" PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.0//EN" "lrml.dtd" PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "lrml.dtd" SYSTEM "http://www.logreport.org/LRML/2.0/lire.dtd" "lrml.dtd" SYSTEM "http://www.logreport.org/LRML/2.0/lrml.dtd" "lrml.dtd" SYSTEM "http://www.logreport.org/LRML/2.1/lrml.dtd" "lrml.dtd" PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.0//EN" "lrcsml.dtd" SYSTEM "http://www.logreport.org/LRCSML/1.0/lrcsml.dtd" "lrcsml.dtd" PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.1//EN" "lrcsml.dtd" SYSTEM "http://www.logreport.org/LRCSML/1.1/lrcsml.dtd" "lrcsml.dtd" PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Markup Language V1.0//EN" "lrcml.dtd" SYSTEM "http://www.logreport.org/LRCML/1.0/lrcml.dtd" "lrcml.dtd" lire-2.1.1/all/lib/xml/dtd/lire-desc.dbx0000644000175000017500000000610711677605734014652 00000000000000
Lire Textual Elements This DTD module defines elements related that contains human-readable content in all the Lire DTDs. This module will also imports some DocBook XML V4.1.2 elements for richer semantic tagging. This module is also namespace aware and will honor the setting of LIRE.pfx to scope its element The latest version of that module is 2.0 and its public identifier is -//LogReport.ORG//ELEMENTS Lire Textual Elements V2.0//EN. <!-- Make sure LIRE.pfx is defined. This declaration will be ignored if it was already defined. --> <!ENTITY % LIRE.pfx "lire:" > <!ENTITY % LIRE.title "%LIRE.pfx;title" > <!ENTITY % LIRE.description "%LIRE.pfx;description" >
<sgmltag>title</sgmltag> element The title element contains a descriptive title. This element represent some title in Lire. It can be used to give a title to a report specification or to specifify the title of a report or subreport. The content of this element should be localized. This element doesn't have any attribute. <!ELEMENT %LIRE.title; (#PCDATA) >
DocBook Elements The standard para, formalpara and admonition elements (note, tip, warning, important and caution) are used as well as their content may be used. <!ENTITY % docbook-block.mix "para|formalpara|warning|tip|important|caution|note"> <!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"> %DocBookDTD;
<sgmltag>description</sgmltag> element The description element is used to describe an element. It can be used to describe DLF fields, describe a report specification or include descriptions in the generated reports. This element can contains one or more of the block-level DocBook elements we use. The content of this element should be localized. This element doesn't have any attributes. <!ELEMENT %LIRE.description; (%docbook-block.mix;)+>
lire-2.1.1/all/lib/xml/dtd/lire-desc.mod0000644000175000017500000000302311677605734014646 00000000000000 %DocBookDTD; lire-2.1.1/all/lib/xml/dtd/lire-desc.xml0000644000175000017500000001062010460673260014654 00000000000000 ]>
Lire Textual Elements 2001-2002 Stichting LogReport Foundation $Revision: 1.4 $ $Date: 2006/07/23 13:16:32 $ $Author: vanbaal $ Copyright (C) 2001,2002 Stichting LogReport Foundation LogReport@LogReport.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. lire-desc &lire-desc-version;
Lire Textual Elements This DTD module defines elements related that contains human-readable content in all the Lire DTDs. This module will also imports some DocBook XML V4.1.2 elements for richer semantic tagging. This module is also namespace aware and will honor the setting of LIRE.pfx to scope its element The latest version of that module is &lire-desc-version; and its public identifier is -//LogReport.ORG//ELEMENTS Lire Textual Elements V&lire-desc-version;//EN. ]]>
<sgmltag>title</sgmltag> element The title element contains a descriptive title. This element represent some title in Lire. It can be used to give a title to a report specification or to specifify the title of a report or subreport. The content of this element should be localized. This element doesn't have any attribute. ]]>
DocBook Elements The standard para, formalpara and admonition elements (note, tip, warning, important and caution) are used as well as their content may be used. %DocBookDTD; ]]>
<sgmltag>description</sgmltag> element The description element is used to describe an element. It can be used to describe DLF fields, describe a report specification or include descriptions in the generated reports. This element can contains one or more of the block-level DocBook elements we use. The content of this element should be localized. This element doesn't have any attributes. ]]>
lire-2.1.1/all/lib/xml/xml.dcl0000644000175000017500000001771310460672602013005 00000000000000" PIC "?>" SHORTREF NONE NAMES SGMLREF QUANTITY NONE ENTITIES "amp" 38 "lt" 60 "gt" 62 "quot" 34 "apos" 39 FEATURES MINIMIZE DATATAG NO OMITTAG NO RANK NO SHORTTAG STARTTAG EMPTY NO UNCLOSED NO NETENABL IMMEDNET ENDTAG EMPTY NO UNCLOSED NO ATTRIB DEFAULT YES OMITNAME NO VALUE NO EMPTYNRM YES IMPLYDEF ATTLIST NO DOCTYPE NO ELEMENT NO ENTITY NO NOTATION NO LINK SIMPLE NO IMPLICIT NO EXPLICIT NO OTHER CONCUR NO SUBDOC NO FORMAL NO URN NO KEEPRSRE YES VALIDITY TYPE ENTITIES REF ANY INTEGRAL YES APPINFO NONE SEEALSO "ISO 8879:1986//NOTATION Extensible Markup Language (XML) 1.0//EN" > lire-2.1.1/all/lib/xml/Makefile.am0000644000175000017500000000211710115242145013535 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.6 2004/09/01 03:39:17 flacoste Exp $ ## Copyright (C) 2000-2001 Stichting LogReport Foundation LogReport@LogReport.org ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. SUBDIRS = dtd EXTRA_DIST = xml.dcl $(srcdir)/stylesheet/xsl/*.xsl lire-2.1.1/all/lib/xml/Makefile.in0000644000175000017500000003764311677606133013601 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = all/lib/xml DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = dtd EXTRA_DIST = xml.dcl $(srcdir)/stylesheet/xsl/*.xsl all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/xml/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/xml/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am clean clean-generic ctags \ ctags-recursive distclean distclean-generic distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ tags-recursive uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lire-2.1.1/all/lib/xml/stylesheet/0000755000175000017500000000000011677607767014006 500000000000000lire-2.1.1/all/lib/xml/stylesheet/xsl/0000755000175000017500000000000011677607767014614 500000000000000lire-2.1.1/all/lib/xml/stylesheet/xsl/make-dtd.xsl0000644000175000017500000000113310460672602016723 00000000000000 <?xml version="1.0" encoding="US-ASCII"?> <!-- --> lire-2.1.1/all/lib/xml/stylesheet/xsl/make-dtddoc.xsl0000644000175000017500000000054410460672602017416 00000000000000 lire-2.1.1/all/lib/Lire/0000755000175000017500000000000011677607767011710 500000000000000lire-2.1.1/all/lib/Lire/UI/0000755000175000017500000000000011677607770012217 500000000000000lire-2.1.1/all/lib/Lire/UI/SelectWidget.pm0000644000175000017500000000270710460672573015056 00000000000000package Lire::UI::SelectWidget; use strict; use base qw/ Curses::UI::Popupmenu Lire::UI::Widget /; use Curses::UI::Common; use Lire::Utils qw/ item_index check_object_param /; use Locale::TextDomain 'lire'; use Carp; use vars qw/@CARP_NOT/; @CARP_NOT = qw/Curses::UI::Container/; sub new { my $class = shift; my %userargs = @_; keys_to_lowercase(\%userargs); check_object_param( $userargs{'value'}, 'value', 'Lire::Config::Scalar' ); my @options = map { $_->name() } $userargs{'value'}->spec()->options(); my $selected; my $focusable; if (@options) { $selected = ( $userargs{'value'}->is_valid() ? item_index( \@options, $userargs{'value'}->get() ) : undef ); $focusable = 1; } else { @options = ( __( '-- empty list --' ) ); $selected = 0; $focusable = 0; } my %args = ( %userargs, '-height' => 1, '-onchange' => \&_on_change_cb, '-selected' => $selected, '-values' => \@options, '-focusable' => $focusable ); return $class->Curses::UI::Popupmenu::new( %args ); } sub layout { my $self = $_[0]; $self->{'-height'} = 1; return $self->SUPER::layout(); } # callbacks sub _on_change_cb { my $self = $_[0]; $self->{'value'}->set( $self->get() ); $self->run_event( 'onvaluechanged' ); return; } 1; lire-2.1.1/all/lib/Lire/UI/IntegerWidget.pm0000644000175000017500000000653310460672573015235 00000000000000package Lire::UI::IntegerWidget; use strict; use base qw/ Curses::UI::Container Lire::UI::Widget /; use Curses::UI::Common; use Curses; use Carp; use vars qw/@CARP_NOT/; use Lire::Utils qw/ check_object_param /; @CARP_NOT = qw/Curses::UI::Container/; my %routines = ( 'increase' => \&increase, 'decrease' => \&decrease ); sub new { my $class = shift; my %userargs = @_; keys_to_lowercase(\%userargs); check_object_param( $userargs{'value'}, 'value', 'Lire::Config::Scalar' ); my $self = $class->Curses::UI::Container::new( %userargs, '-height' => 1, '-routines' => \%routines, '-releasefocus' => 1, '-border' => 0 ); $self->set_binding( sub { $self->do_routine( 'decrease' ) }, '-', KEY_LEFT() ); $self->set_binding( sub { $self->do_routine( 'increase' ) }, '+', KEY_RIGHT() ); $self->set_binding( sub { $self->do_routine( 'decrease', 10 ) }, KEY_DOWN() ); $self->set_binding( sub { $self->do_routine( 'increase', 10 ) }, KEY_UP() ); $self->add( 'text_entry', 'TextEntry', '-sbborder' => 1, '-height' => 1, '-text' => $userargs{'value'}->get(), '-regexp' => '/^[0-9]*$/', '-onchange' => \&_on_change_cb ); $self->add( 'buttons', 'Buttonbox', '-width' => 7, '-buttons' => [ { '-label' => '[<]', '-onpress' => sub { $self->do_routine( 'decrease' ) }, }, { '-label' => '[>]', '-onpress' => sub { $self->do_routine( 'increase' ) }, } ] ); $self->layout(); return $self; } sub layout { my $self = $_[0]; $self->{'-height'} = 1; return $self->SUPER::layout(); } sub layout_contained_objects { my $self = $_[0]; return $self unless $self->getobj( 'text_entry' ); my $width = $self->canvaswidth(); my $entry = $self->getobj( 'text_entry' ); my $box = $self->getobj( 'buttons' ); if ( $width < 18 ) { $box->hide(); $entry->{'-width'} = $width; } else { $box->show(); $entry->{'-width'} = $width - 8; $box->{'-x'} = $entry->{'-width'} + 1; } return $self->SUPER::layout_contained_objects(); } sub refresh_view { my $self = $_[0]; my $text_entry = $self->getobj( 'text_entry' ); $text_entry->text( $self->{'value'}->get() ); return; } # Routines sub decrease { my ( $self, $offset ) = @_; $offset ||= 1; my $value = $self->{'value'}->get() || 0; $self->{'value'}->set( $value - $offset ); $self->refresh_view(); return; } sub increase { my ( $self, $offset ) = @_; $offset ||= 1; my $value = $self->{'value'}->get() || 0; $self->{'value'}->set( $value + $offset ); $self->refresh_view(); return; } # callbacks sub _on_change_cb { my $text_entry = $_[0]; my $self = $text_entry->parent(); $self->{'value'}->set( $text_entry->{'-text'} ); $self->run_event( 'onvaluechanged' ); return; } 1; lire-2.1.1/all/lib/Lire/UI/CommandWidget.pm0000644000175000017500000000037410460672573015213 00000000000000package Lire::UI::CommandWidget; use strict; use base qw/ Lire::UI::ExecutableWidget /; use Locale::TextDomain 'lire'; sub invalid_label_str { return __( 'Invalid command' ); } sub browser_title_str { return __( 'Select a Command'); } 1; lire-2.1.1/all/lib/Lire/UI/ReportConfigListWidget.pm0000644000175000017500000000142310460672573017066 00000000000000package Lire::UI::ReportConfigListWidget; use strict; use base qw/ Lire::UI::PolyListWidget /; use Lire::ReportConfig; sub update_type_popupmenu { my $self = $_[0]; my $popup = $self->getobj( 'type_widget' ); $popup->{'-values'} = [ sort @{Lire::ReportConfig->templates()} ]; $popup->{'-labels'} = {}; return; } sub new_value { my $self = $_[0]; my $template = $self->getobj( 'type_widget' )->get(); return undef unless defined $template; # We need to switch the spec object if we hope to # get the list object to accept this instance my $value = Lire::ReportConfig->template( $template )->clone(); my $spec = $self->{'value'}->spec(); $value->{'spec'} = $spec->get( ($spec->component_names())[0] ); return $value; } 1; lire-2.1.1/all/lib/Lire/UI/Widget.pm0000644000175000017500000001242710460673260013710 00000000000000package Lire::UI::Widget; use strict; use Carp; use Curses::UI::Common; use Lire::Utils qw/ check_object_param /; use base qw/ Curses::UI::Widget /; use vars qw/@CARP_NOT/; @CARP_NOT = qw/Curses::UI::Container/; =pod =head1 NAME Lire::UI::Widget - Views for Lire::Config::Value object. =head1 SYNOPSIS use Curses::UI; use Lire::Config; Lire::Config->init(); my $ui = new Curses::UI(); my $window = $ui->add( 'window', 'Window' ); my $widget = $window->add( 'widget', 'Lire::UI::Widget', 'value' => Lire::Config->get_var( 'name' )); =head1 DESCRIPTION Lire::UI::Widget defines Curses::UI::Widget subclasses that can be used to edit Lire::Config::Value object. =cut use vars qw/ %widget_table /; %widget_table = ( 'Lire::Config::BooleanSpec' => 'Lire::UI::BoolWidget', 'Lire::Config::ChartSpec' => 'Lire::UI::CompoundWidget', 'Lire::Config::ChartTypeSpec' => 'Lire::UI::PluginWidget', 'Lire::Config::CommandSpec' => 'Lire::UI::CommandWidget', 'Lire::Config::DirectorySpec'=>'Lire::UI::DirectoryWidget', 'Lire::Config::DlfAnalyserSpec' => 'Lire::UI::PluginWidget', 'Lire::Config::DlfConverterSpec' => 'Lire::UI::PluginWidget', 'Lire::Config::DlfSchemaSpec' => 'Lire::UI::SelectWidget', 'Lire::Config::DlfStreamSpec' => 'Lire::UI::CompoundWidget', 'Lire::Config::ExecutableSpec'=>'Lire::UI::ExecutableWidget', 'Lire::Config::FileSpec' => 'Lire::UI::FileWidget', 'Lire::Config::IntegerSpec' => 'Lire::UI::IntegerWidget', 'Lire::Config::ListSpec' => 'Lire::UI::ListWidget', 'Lire::Config::ObjectSpec' => 'Lire::UI::CompoundWidget', 'Lire::Config::OutputFormatSpec' => 'Lire::UI::PluginWidget', 'Lire::Config::PluginSpec' => 'Lire::UI::PluginWidget', 'Lire::Config::RecordSpec' => 'Lire::UI::CompoundWidget', 'Lire::Config::ReferenceSpec' => 'Lire::UI::SelectWidget', 'Lire::Config::ReportSectionSpec' => 'Lire::UI::ReportSectionWidget', 'Lire::Config::ReportSpec' => 'Lire::UI::CompoundWidget', 'Lire::Config::SelectSpec' => 'Lire::UI::SelectWidget', 'Lire::Config::XMLSpecListSpec' => 'Lire::UI::XMLSpecListWidget', 'Lire::Config::StringSpec' => 'Lire::UI::StringWidget', ); =pod =head2 new( %args, 'value' => $value, [ onvaluechanged => $handler ] ) The new() method is really a factory method which instantiate a proper Lire::UI::Widget subclass based on the type of the Lire::Config::Value $value. The onvaluechanged is an event that will be trigger whenever the Lire::Config::Value is modified by the user. =cut sub new { my $class = shift; my %userargs = @_; keys_to_lowercase(\%userargs); check_object_param( $userargs{'value'}, 'value', 'Lire::Config::Value' ); my $spec_type = ref( $userargs{'value'}->spec() ); croak "no widget type defined for values of type '$spec_type'" unless exists( $widget_table{$spec_type} ); my $widget_class = $widget_table{$spec_type}; eval "use $widget_class;"; die if $@; return $widget_class->new( %userargs ); } =pod =head2 value() Returns the Lire::Config::Value object which is edited by this view. =cut sub value { return $_[0]{'value'}; } =pod =head2 onValueChanded( $code ) Changes the event handler connected to the 'onvaluechanged' event. This event is trigger whenever the Lire::Config::Value associated to this widget is modified. =cut sub onValueChanged { my ( $self, $handler ) = @_; $self->set_event( 'onvaluechanged', $handler ); return; } =pod =head2 refresh_view() This method can be called to update the view to reflect modifications to the underlying Lire::COnfig::Value. =cut sub refresh_view { croak "unimplemented refresh_view() in ", ref $_[0]; } package Lire::UI::DummyWidget; $INC{'Lire/UI/DummyWidget.pm'} = __FILE__; use base qw/Curses::UI::TextViewer/; use Carp; sub new { my ( $class, %args ) = @_; return $class->SUPER::new( %args, '-text' => $args{'value'}->get() ); } sub refresh_view { $_[0]->text( $_[0]->{'value'}->get() ); } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::UI(3pm), Curses::UI(3pm) =head1 VERSION $Id: Widget.pm,v 1.27 2006/07/23 13:16:32 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/UI/FileWidget.pm0000644000175000017500000000732210460672573014514 00000000000000package Lire::UI::FileWidget; use strict; use base qw/ Curses::UI::Container Lire::UI::Widget /; use Curses::UI::Common; use Carp; use vars qw/@CARP_NOT/; use Lire::Utils qw/ check_object_param /; use Lire::UI::Utils qw/button_label/; use Locale::TextDomain 'lire'; @CARP_NOT = qw/Curses::UI::Container/; sub new { my $class = shift; my %userargs = @_; keys_to_lowercase(\%userargs); check_object_param( $userargs{'value'}, 'value', 'Lire::Config::Scalar' ); my $self = $class->Curses::UI::Container::new( %userargs, '-height' => 2, '-releasefocus' => 1, '-border' => 0 ); my $file_field = $self->add( 'file_field', 'TextEntry', '-height' => 1, '-sbborder' => 1, '-text' => $userargs{'value'}->get(), '-onchange' => \&_on_change_cb ); my $browse_btn = $self->add( 'browse_btn', 'Buttonbox', '-y' => 1, '-buttons' => [ { '-label' => button_label( __( 'Browse' )), '-onpress' => \&_browse_cb } ] ); $self->add( 'warn_label', 'Label', '-text' => '', '-y' => 1, '-bold' => '1' ); # Buttonbox as last focus in a releasefocus container # doesn't work too well with Curses::UI $self->set_focusorder( 'browse_btn', 'file_field' ); $self->_refresh_warn_label(); $self->layout(); return $self; } sub layout { my $self = $_[0]; $self->{'-height'} = 2; return $self->SUPER::layout(); } sub layout_contained_objects { my $self = $_[0]; my $browse_btn = $self->getobj( 'browse_btn' ); return $self unless $browse_btn; $browse_btn->{'-width'} = length $browse_btn->{'-buttons'}[0]{'-label'}; my $label = $self->getobj( 'warn_label' ); $label->{'-x'} = $browse_btn->{'-width'} + 1; $label->{'-width'} = length( $self->invalid_label_str() ); return $self->SUPER::layout_contained_objects() } sub refresh_view { my $self = $_[0]; my $file_widget = $self->getobj( 'file_field' ); $file_widget->text( $self->{'value'}->get() ); $self->_refresh_warn_label(); return; } sub _refresh_warn_label { my $self = $_[0]; my $warn_label = $self->getobj( 'warn_label' ); $warn_label->text( $self->{'value'}->spec()->is_valid( $self->{'value'}->get() ) ? '' : $self->invalid_label_str() ); return; } # template methods sub invalid_label_str { return __( 'Invalid filename' ); } sub browser_title_str { return __( 'Select a File'); } sub browse_dialog { my $self = $_[0]; my $file_field = $self->getobj( 'file_field' ); return $self->root()->filebrowser( '-title' => $self->browser_title_str(), '-file' => $file_field->get(), '-editfilename' => 1, '-show_hidden' => 1 ); } # callback functions sub _on_change_cb { my $file_widget = $_[0]; my $self = $file_widget->parent(); $self->{'value'}->set( $file_widget->{'-text'} ); $self->_refresh_warn_label(); $self->run_event( 'onvaluechanged' ); return; } sub _browse_cb { my $button = $_[0]; my $self = $button->parent(); my $file_field = $self->getobj( 'file_field' ); my $new_file = $self->browse_dialog(); if ( defined $new_file ) { $file_field->text( $new_file ); _on_change_cb( $file_field ); } return; } 1; lire-2.1.1/all/lib/Lire/UI/PolyListWidget.pm0000644000175000017500000000225610460672573015415 00000000000000package Lire::UI::PolyListWidget; use strict; use base qw/ Lire::UI::CompoundListWidget /; # List API sub add_contained_widgets { my $self = $_[0]; $self->add( 'type_widget', 'Curses::UI::Popupmenu' ); $self->update_type_popupmenu(); $self->SUPER::add_contained_widgets(); return; } sub extra_widget_height { return 1; } sub layout_contained_objects { my $self = $_[0]; my $popup = $self->getobj( 'type_widget' ); return $self unless $popup; $popup->{'-width'} = $self->canvaswidth() - 2; $popup->{'-x'} = 1; $popup->{'-y'} = $self->canvasheight() - 2; return $self->SUPER::layout_contained_objects(); } sub update_type_popupmenu { my $self = $_[0]; my %menu = (); foreach my $comp ( $self->{'value'}->spec()->components() ) { $menu{ $comp->summary() } = $comp; } my $popup = $self->getobj( 'type_widget' ); $popup->{'-values'} = [ map { $menu{$_} } sort keys %menu ]; $popup->{'-labels'} = { map { $menu{$_} => $_ } sort keys %menu }; return; } sub new_value { my $self = $_[0]; my $spec = $self->getobj( 'type_widget' )->get(); return $spec ? $spec->instance() : undef; } 1; lire-2.1.1/all/lib/Lire/UI/ScalarListWidget.pm0000644000175000017500000000547510460672573015705 00000000000000package Lire::UI::ScalarListWidget; use strict; use base qw/ Lire::UI::ListWidget /; use Locale::TextDomain 'lire'; use Carp; sub new { my $class = shift; my $self = $class->SUPER::new( @_ ); $self->getobj( 'list' )->onChange( \&_value_change_cb ); $self->set_routine( 'apply-changes', \&apply_changes ); return $self; } # List API sub add_contained_widgets { my $self = $_[0]; my $selected = $self->getobj( 'list' )->{'-selected'}; my $value = ( defined $selected ? $self->{'value'}->get( $selected )->clone() : $self->{'component'}->instance() ); $self->add( 'value_widget', 'Lire::UI::Widget', 'value' => $value ); $self->SUPER::add_contained_widgets(); return; } sub add_buttons_widget { my $self = $_[0]; $self->SUPER::add_buttons_widget(); my $buttons = $self->getobj( 'buttons' ); splice @{$buttons->{'-buttons'}}, 1, 0, { '-label' => __( 'Apply' ), '-onpress' =>sub { $self->do_routine( 'apply-changes' ) } }; return; } sub extra_widget_height { my $self = $_[0]; # Scalar widget have an invariant height; return $self->getobj( 'value_widget' )->{'-height'}; } sub layout_contained_objects { my $self = $_[0]; my $value = $self->getobj( 'value_widget' ); return $self unless $value; $value->{'-width'} = $self->canvaswidth() - 2; $value->{'-x'} = 1; $value->{'-y'} = $self->canvasheight() - (1 + $value->{'-height'}); return $self->SUPER::layout_contained_objects(); } sub layout_buttons { my $self = $_[0]; $self->getobj( 'buttons' )->{'-buttons'}[1]{'-label'} = __( 'Apply' ); $self->SUPER::layout_buttons(); return; } sub new_value { my $self = $_[0]; my $value = $self->getobj( 'value_widget' )->{'value'}; return $self->{'component'}->instance( 'value' => $value->get() ); } # Routines sub apply_changes { my $self = $_[0]; my $list_widget = $self->getobj( 'list' ); my $value_widget = $self->getobj( 'value_widget' ); return unless defined $list_widget->{'-selected'}; my $value = $self->{'value'}->get( $list_widget->{'-selected'} ); $value->set( $value_widget->{'value'}->get() ); $self->refresh_view(); $self->run_event( 'onvaluechanged' ); return; } # Event handlers sub _value_change_cb { my $list_widget = $_[0]; croak "'-selected' can never be undefined" unless defined $list_widget->{'-selected'}; my $self = $list_widget->parent(); return unless ( $self->{'component'}->isa('Lire::Config::ScalarSpec') ); my $new_value = $self->{'value'}->get( $list_widget->{'-selected'} ); my $value_widget = $list_widget->parent()->getobj( 'value_widget' ); $value_widget->{'value'}->set( $new_value->get() ); $value_widget->refresh_view(); return; } 1; lire-2.1.1/all/lib/Lire/UI/ExecutableWidget.pm0000644000175000017500000000040010460672573015704 00000000000000package Lire::UI::ExecutableWidget; use strict; use base qw/ Lire::UI::FileWidget /; use Locale::TextDomain 'lire'; sub invalid_label_str { return __( 'Invalid executable' ); } sub browser_title_str { return __( 'Select an Executable'); } 1; lire-2.1.1/all/lib/Lire/UI/Prefs.pm0000644000175000017500000001666210460673260013551 00000000000000package Lire::UI::Prefs; use strict; use Curses; use Curses::UI; use Lire::Config; use Lire::Utils qw/ check_object_param /; use Locale::TextDomain 'lire'; use Carp; =pod =head1 NAME Lire::UI::Prefs - Preferences management =head1 SYNOPSIS use Lire::UI::Prefs; =head1 DESCRIPTION XXX FIXME =cut sub new { my ( $class, $ui, $config ) = @_; check_object_param( $ui, 'ui', 'Curses::UI' ); check_object_param( $config, 'config', 'Lire::Config::ConfigFile' ); my $self = bless( { '_ui' => $ui, '_cfg_file' => $config }, $class ); $self->_create_prefs_win(); return $self; } sub show { my $self = $_[0]; my $prefs_win = $self->{ '_ui' }->getobj( 'prefs_win' ); my $section_menu = $prefs_win->getobj( 'section_menu' ); $section_menu->{'-selected'} = 0; $section_menu->run_event( '-onchange' ); $prefs_win->modalfocus(); $self->{ '_ui' }->delete( 'prefs_win' ); return; } sub _create_prefs_win { my $self = $_[0]; my $ui = $self->{'_ui'}; my $prefs_win = $ui->add( 'prefs_win', 'Window', '-title' => __( 'Lire Preferences' ), '-y' => 1, '-border' => 1, '-ipadleft' => 1, '-ipadright' => 1, '-ipadtop' => 1 ); $prefs_win->userdata( $self ); $self->_create_section_menu( $prefs_win ); my $width = $prefs_win->getobj( 'section_menu' )->canvaswidth() + 2; $prefs_win->add( 'options_list', 'Listbox', '-values' => [], '-labels' => {}, '-ipadleft' => 1, '-ipadright' => 1, '-y' => 1, '-width' => $width, '-height' => ( $prefs_win->canvasheight() - 1 ), '-onchange' => \&_option_change_cb, '-onselchange' => \&_option_selchange_cb, '-border' => 1 ); $prefs_win->add( 'option_summary', 'Label', '-text' => '', '-bold' => 1, '-width' => ( $prefs_win->canvaswidth() - $width - 3 ), '-x' => $width + 2 ); $prefs_win->add( 'option_help', 'TextViewer', '-x' => $width + 1, '-y' => 14, '-border' => 0, '-padbottom' => 2, '-wrapping' => 1, '-vscrollbar' => 1, '-ipadleft' => 1, '-ipadright' => 1, '-text' => '' ); $self->_create_buttons( $prefs_win ); return; } sub _create_section_menu { my ( $self, $win ) = @_; my @values = ( 'report', 'responder', 'operation', 'path', 'docbook', 'programs' ); my @labels = ( __( 'Reports' ), __( 'Responder Preferences' ), __( 'Operational Preferences' ), __( 'Lire Paths' ), __( 'Docbook Paths' ), __( 'Program Paths' ) ); my $labels = {}; for ( my $i = 0; $i < @values; $i++ ) { $labels->{$values[$i]} = $labels[$i]; } my $section_menu = $win->add( 'section_menu', 'Popupmenu', '-selected' => 0, '-labels' => $labels, '-values' => \@values, '-onchange' => \&_section_change_cb ); return; } sub _create_buttons { my ( $self, $win ) = @_; my $buttons = $win->add( 'buttons', 'Buttonbox', '-buttons' => [ { '-label' => __( '< Cancel >' ), '-onpress' => \&_cancel_cb }, { '-label' => __( '< OK >' ), '-onpress' => \&_ok_cb, } ], '-padleft' => 30, '-y' => -1, '-buttonalignment' => 'right' ); return; } sub _get_var { my ( $self, $name ) = @_; if ( ! $self->{'_cfg_file'}->is_set( $name ) ) { my $clone = Lire::Config->get_var( $name )->clone(); $self->{'_cfg_file'}->set( $clone ); } return $self->{'_cfg_file'}->get( $name ); } # callback functions sub _section_change_cb { my $widget = $_[0]; my $self = $widget->parent()->userdata(); my $options = $self->{'_cfg_file'}->spec()->components_by_section( $widget->get() ); my $options_list = $widget->parent()->getobj( 'options_list' ); my $labels = { map { $_ => $_->name() } @$options }; $options_list->{'-values'} = $options; $options_list->{'-labels'} = $labels; $options_list->{'-ypos'} = 0; $options_list->run_event( '-onselchange' ); $options_list->draw(); return; } sub _option_selchange_cb { my $widget = $_[0]; $widget->{'-selected'} = $widget->{'-ypos'}; $widget->run_event( '-onchange' ); return; } sub _option_change_cb { my $widget = $_[0]; $widget->{'-ypos'} = $widget->{'-selected'}; my $self = $widget->parent()->userdata(); my $option = $widget->get(); my $opt_summary = $widget->parent()->getobj( 'option_summary' ); my $opt_help = $widget->parent()->getobj( 'option_help' ); $opt_help->cursor_up( undef, $opt_help->{'-yscrpos'} ) if ( $opt_help->{'-yscrpos'} > 1 ); if ( !defined $option ) { $widget->{'-ypos'} = 0; $widget->{'-selected'} = undef; $opt_summary->text( '' ); $opt_help->text( '' ); } else { $widget->parent()->delete( 'option_widget' ) if $widget->parent()->getobj( 'option_widget' ); $widget->parent()->add( 'option_widget', 'Lire::UI::Widget', '-x' => $opt_summary->{'-x'}, '-y' => $opt_summary->{'-y'} + 2, '-height' => 11, 'value' => $self->_get_var( $option->name() )); $opt_summary->text( $option->summary() ); $opt_help->text( $option->text_description() || __( 'No help available.' ) ); $widget->parent()->intellidraw(); } return; } sub _cancel_cb { my $buttons = $_[0]; my $prefs_win = $buttons->parent(); $prefs_win->loose_focus(); my $self = $prefs_win->userdata(); $self->{'_cfg_file'}->revert(); return; } sub _ok_cb { my $buttons = $_[0]; my $prefs_win = $buttons->parent(); $prefs_win->loose_focus(); my $self = $prefs_win->userdata(); $self->{'_cfg_file'}->save(); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::UI(3pm) =head1 VERSION $Id: Prefs.pm,v 1.20 2006/07/23 13:16:32 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/UI/StoreWindow.pm0000644000175000017500000003116710460672574014762 00000000000000package Lire::UI::StoreWindow; use strict; use base qw/ Curses::UI::Window /; use Carp; use Curses::UI::Common; use Locale::TextDomain 'lire'; use Time::Local; use Lire::Utils qw/ check_param check_object_param max text_for_width /; use Lire::UI::Utils qw/ button_box_width /; use POSIX qw/strftime/; use vars qw/ @CARP_NOT /; @CARP_NOT = qw/ Curses::UI::Container /; my %routines = ( 'configure-stream' => \&configure_stream, 'clean-stream' => \&clean_stream, ); sub new { my $class = shift; my %userargs = @_; keys_to_lowercase( \%userargs ); check_object_param( $userargs{'store'}, 'store', 'Lire::DlfStore' ); my $self = $class->SUPER::new( %userargs, '-titlereverse' => 0, '-border' => 1, '-routines' => \%routines, '-ipad' => 1, '-ipadbottom' => 0, ); $self->add( 'import_jobs', 'Lire::UI::Widget', 'value' => $self->{'store'}->config()->get( 'import_jobs' ), '-title' => __( 'Import Jobs' ), '-titlereverse' => 0 ); $self->add( 'report_jobs', 'Lire::UI::Widget', 'value' => $self->{'store'}->config()->get( 'report_jobs' ), '-title' => __( 'Report Jobs' ), '-titlereverse' => 0 ); $self->getobj( 'import_jobs' )->onValueChanged( sub { $self->_update_streams(); $self->getobj( 'streams' )->intellidraw() } ); $self->add( 'reports', 'Lire::UI::ReportConfigListWidget', 'value' => $self->{'store'}->config()->get( 'reports' ), '-title' => __( 'Report Configurations' ), '-titlereverse' => 0 ); $self->_add_stream_widgets(); $self->layout(); return $self; } sub layout_contained_objects { my $self = $_[0]; # Contained widgets weren't added yet. return $self unless $self->getobj( 'import_jobs' ); # Window contains 4 quadrants my $win_w = $self->canvaswidth(); my $w = int( ( $win_w - 1) / 2 ); my $h = int( ($self->canvasheight() - 1) / 2 ); my $store_label = __( 'Store: ' ); $self->title( $store_label . text_for_width( $self->{'store'}->path(), $win_w - ( 4 + length( $store_label ) ) )); my $import_jobs = $self->getobj( 'import_jobs' ); $import_jobs->{'-width'} = $w; $import_jobs->{'-height'} = $h; my $report_jobs = $self->getobj( 'report_jobs' ); $report_jobs->{'-x'} = $w + 1; $report_jobs->{'-width'} = $w; $report_jobs->{'-height'} = $h; my $reports = $self->getobj( 'reports' ); $reports->{'-y'} = $h + 1; $reports->{'-width'} = $w; $reports->{'-height'} = $h; $self->_set_stream_widgets_coor( $h, $w ); return $self->SUPER::layout_contained_objects(); } sub _set_stream_widgets_coor { my ($self, $h, $w ) = @_; my $streams = $self->getobj( 'streams' ); $streams->{'-width'} = $w - 1; # To align with ListWidget $streams->{'-height'} = $h - 4; $streams->{'-y'} = $h + 1; $streams->{'-x'} = $w + 1; my $y = $h + ( $h - 4 ) + 1; my $buttons = $self->getobj( 'streams_buttons' ); $buttons->{'-x'} = $w + 2; $buttons->{'-y'} = $y++; $y++; my $max_label_w = max( $self->getobj( 'stream_start_label' )->width(), $self->getobj( 'stream_end_label' )->width(), $self->getobj( 'nrecords_label' )->width() ); foreach my $name ( qw/stream_start stream_end nrecords/ ) { my $label = $self->getobj( "${name}_label" ); my $value = $self->getobj( "${name}_value" ); $label->{'-x'} = $w + 2; $value->{'-x'} = $w + $max_label_w + 2; $label->{'-y'} = $value->{'-y'} = $y++; } return; } sub _add_stream_widgets { my $self = $_[0]; my $streams = $self->add( 'streams', 'Listbox', '-onchange' => \&_change_cb, '-onselchange' => \&_sel_change_cb, '-values' => [], '-title' => __( 'DLF Streams' ), '-titlereverse' => 0, '-selected' => undef, '-ypos' => undef, '-vscrollbar' => 1, '-focusable' => 0, '-border' => 1, ); $streams->set_binding( sub { $self->do_routine( 'configure-stream' ) }, Curses::KEY_ENTER ); $streams->set_binding( sub { $self->do_routine( 'clean-stream' ) }, Curses::KEY_DC, Curses::KEY_BACKSPACE ); $self->add( 'stream_start_label', 'Label', '-text' => __( 'Starts:' ) ); $self->add( 'stream_end_label', 'Label', '-text' => __( 'Ends:' ) ); $self->add( 'nrecords_label', 'Label', '-text' => __( 'Records:' ) ); $self->add( 'stream_start_value', 'Label' ); $self->add( 'stream_end_value', 'Label' ); $self->add( 'nrecords_value', 'Label' ); $self->add( 'streams_buttons', 'Buttonbox', '-buttons' => [ { '-label' => __( '[Configure]' ), '-onpress' => sub { $self->do_routine( 'configure-stream' ) } }, { '-label' => __( '[Clean]' ), '-onpress' => sub { $self->do_routine( 'clean-stream' ) } } ], ); $self->_update_streams(); return; } sub _clean_ok_cb_helper { my ( $self, $time_field ) = @_; my $dialog = $self->getobj( 'stream_clean' ); my $streams = $self->getobj( 'streams' ); my $stream_name = $streams->get(); my $stream = $self->{'store'}->open_dlf_stream( $stream_name, 'w' ); my $time = _date_to_epoch( $time_field->text() ); $stream->clean( $time ); $stream->close(); $self->_update_labels(); return; } sub clean_stream { my $self = $_[0]; my $streams = $self->getobj( 'streams' ); return unless $streams->{'-focusable'}; my $title = __x( "Cleaning stream '{stream}'", 'stream' => $streams->get() ); my $dialog = $self->add( 'clean_stream_win', 'Window', '-title' => $title, '-ipad' => 1, '-x' => 7, '-y' => 8, '-height' => 9, '-width' => 60, '-border' => 1 ); $dialog->set_binding( sub { $dialog->loose_focus() }, CUI_ESCAPE ); $dialog->add( 'question', 'Label', '-text' => __( 'Enter the cleaning date in the form "YYYY-MM-DD":' ), '-x' => 0, '-y' => 0 ); my $time_field = $dialog->add( 'time_field', 'TextEntry', '-regexp' => '/^[0-9-]*$/', '-sbborder' => 1, '-x' => 20, '-y' => 2, '-width' => 14 ); my $buttons = [ { '-label' => __( '< Cancel >' ), '-onpress' => sub { $dialog->loose_focus() } }, { '-label' => __( '< OK >' ), '-onpress' => sub { if ( _test_date ( $time_field->text() ) ) { $self->_clean_ok_cb_helper( $time_field ); $dialog->loose_focus(); } } } ]; my $bb_width = button_box_width( $buttons ); $dialog->add( 'buttons', 'Buttonbox', '-buttons' => $buttons, '-x' => -20, '-y' => 4, '-height' => 1, '-width' => $bb_width ); $dialog->modalfocus(); $self->delete( 'clean_stream_win' ); $self->draw( 1 ); return; } sub configure_stream { my $self = $_[0]; my $streams = $self->getobj( 'streams' ); return unless $streams->{'-focusable'}; my $dialog = $self->root->add( 'configure_stream_win', 'Window', '-title' => __x( "Configuring stream '{stream}'", 'stream' => $streams->get() ), '-ipadleft' => 1, '-ipadright' => 1, '-ipadtop' => 1, '-pad' => 2, '-border' => 1 ); $dialog->set_binding( sub { $dialog->loose_focus() }, CUI_ESCAPE ); my $config_value = $self->{'store'}->get_stream_config( $streams->get() )->clone(); $dialog->add( 'stream_config', 'Lire::UI::Widget', 'value' => $config_value, '-releasefocus' => 1, '-ipadbottom' => 2 ); my $buttons = [ { '-label' => __( '< Cancel >' ), '-onpress' => sub { $dialog->loose_focus() } }, { '-label' => __( '< OK >' ), '-onpress' => sub { $self->_configure_ok_cb_helper( $config_value ); $dialog->loose_focus(); } } ]; my $bb_width = button_box_width( $buttons ); $dialog->add( 'buttons', 'Buttonbox', '-buttons' => $buttons, '-x' => -$bb_width, '-y' => -1, '-width' => $bb_width ); $dialog->modalfocus(); $self->root()->delete( 'configure_stream_win' ); $self->draw( 1 ); return; } sub _configure_ok_cb_helper { my ( $self, $new_config_value ) = @_; my $old = $self->{'store'}->get_stream_config( $self->getobj( 'streams' )->get() ); # Since we do not have access to the stream config list container, we # copy the content. foreach my $name ( $old->spec()->component_names() ) { $old->set( $new_config_value->get( $name ) ); } $self->_update_streams(); return; } sub _update_streams { my $self = $_[0]; my @streams = $self->{'store'}->configured_dlf_streams(); my $values; my $selected; my $focusable; if ( @streams ) { $values = \@streams; $selected = 0; $focusable = 1; } else { $values = [ __( '-- no stream --' ) ]; $selected = undef; $focusable = 0; } my $stream_widget = $self->getobj( 'streams' ); $stream_widget->{'-values'}= $values; $stream_widget->{'-selected'} = $selected; $stream_widget->{'-ypos'} = 0; $stream_widget->focusable( $focusable ); $self->_update_labels(); return; } sub _update_labels { my $self = $_[0]; my $stream_name = $self->getobj( 'streams' )->get(); my $start_value; my $end_value; my $nrecords; if ( defined $stream_name && $self->{'store'}->has_dlf_stream( $stream_name ) ) { my $stream = $self->{'store'}->open_dlf_stream( $stream_name ); $start_value = _epoch_to_date( $stream->start_time() ); $end_value = _epoch_to_date( $stream->end_time() ); $nrecords = $stream->nrecords(); $stream->close(); } else { $start_value = ''; $end_value = ''; $nrecords = defined $stream_name ? 0 : ''; } $self->getobj( 'stream_start_value' )->text( $start_value ); $self->getobj( 'stream_end_value' )->text( $end_value ); $self->getobj( 'nrecords_value' )->text( $nrecords ); return; } sub store { return $_[0]->{'store'}; } # callbacks sub _sel_change_cb { my $list_widget = $_[0]; $list_widget->{'-selected'} = $list_widget->{'-ypos'}; $list_widget->run_event( '-onchange' ); return; } sub _change_cb { my $list_widget = $_[0]; croak "'-selected' can never be undefined" unless defined $list_widget->{'-selected'}; my $self = $list_widget->parent(); $self->_update_labels(); return; } # helper functions sub _test_date { my $text = $_[0]; return 0 unless ( $text =~ m/^(\d{2}|\d{4})-(\d{2})-(\d{2})$/ ); my $month = $2; my $day = $3; return 0 if ( $month < 1 || $month > 12 ); return 0 if ( $day < 1 || $day > 31 ); return 1; } sub _date_to_epoch { my $date = $_[0]; check_param( $date, 'date', \&_test_date, "wrong format for 'date' (yyyy-mm-dd)" ); $date =~ m/^(\d{2}|\d{4})-(\d{2})-(\d{2})$/; my $year = $1; my $month = $2 - 1; my $day = $3; return timelocal( 0, 0, 0, $day, $month, $year ); } sub _epoch_to_date { my $epoch = $_[0]; return __( '-- no date --' ) unless $epoch; check_param( $epoch, 'epoch', qr/^\d+$/, "'epoch' should be a positive integer" ); return strftime( '%Y-%m-%d %H:%S', localtime $epoch ); } 1; lire-2.1.1/all/lib/Lire/UI/ReportSectionWidget.pm0000644000175000017500000000203010460672573016424 00000000000000package Lire::UI::ReportSectionWidget; use strict; use base qw/ Lire::UI::CompoundWidget /; use Lire::Utils qw/check_object_param/; use Curses::UI::Common; use Carp; sub new { my ( $class, %userargs ) = @_; keys_to_lowercase(\%userargs); my $value = $userargs{'value'}; check_object_param( $value, 'value', 'Lire::Config::Dictionary' ); croak "'value' parameter's spec should be a 'Lire::Config::ReportSectionSpec' instance, not '", $value->spec(), "'" unless $value->spec()->isa( 'Lire::Config::ReportSectionSpec' ); my $self = $class->SUPER::new( %userargs ); $self->getobj( 'superservice_widget' )->onValueChanged( sub { $self->update_spec_widgets() } ); $self->update_spec_widgets(); return $self; } sub update_spec_widgets { my $self = $_[0]; my $superservice = $self->{'value'}->get( 'superservice' )->get(); $self->getobj( 'filters_widget' )->superservice_filter( $superservice ); $self->getobj( 'specs_widget' )->superservice_filter( $superservice ); return; } 1; lire-2.1.1/all/lib/Lire/UI/Makefile.am0000644000175000017500000000336110074046652014160 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.17 2004/07/10 20:12:26 flacoste Exp $ ## Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org ## ## This file is part of Lire. ## ## Lire is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk SUBDIRS = allperllibdir = $(LR_PERL5LIBDIR)/Lire/UI pm_s = \ Prefs.pm \ Utils.pm \ BoolWidget.pm \ CommandWidget.pm \ CompoundWidget.pm \ CompoundListWidget.pm \ DirectoryWidget.pm \ ExecutableWidget.pm \ FileWidget.pm \ IntegerWidget.pm \ ListWidget.pm \ PluginWidget.pm \ PolyListWidget.pm \ ReportConfigListWidget.pm \ ReportSectionWidget.pm \ ScalarListWidget.pm \ SelectWidget.pm \ StoreWindow.pm \ StringWidget.pm \ XMLSpecListWidget.pm \ Widget.pm allperllib_DATA = $(pm_s) man_MANS = \ Prefs.3pm \ Utils.3pm \ Widget.3pm perlpackage = Lire::UI transform = s,^,$(perlpackage)::, EXTRA_DIST = $(pm_s) CLEANFILES = $(man_MANS) lire-2.1.1/all/lib/Lire/UI/Makefile.in0000644000175000017500000006200211677606132014173 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/include/rules.mk subdir = all/lib/Lire/UI ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(allperllib_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" transform = s,^,$(perlpackage)::, ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done SUBDIRS = allperllibdir = $(LR_PERL5LIBDIR)/Lire/UI pm_s = \ Prefs.pm \ Utils.pm \ BoolWidget.pm \ CommandWidget.pm \ CompoundWidget.pm \ CompoundListWidget.pm \ DirectoryWidget.pm \ ExecutableWidget.pm \ FileWidget.pm \ IntegerWidget.pm \ ListWidget.pm \ PluginWidget.pm \ PolyListWidget.pm \ ReportConfigListWidget.pm \ ReportSectionWidget.pm \ ScalarListWidget.pm \ SelectWidget.pm \ StoreWindow.pm \ StringWidget.pm \ XMLSpecListWidget.pm \ Widget.pm allperllib_DATA = $(pm_s) man_MANS = \ Prefs.3pm \ Utils.3pm \ Widget.3pm perlpackage = Lire::UI EXTRA_DIST = $(pm_s) CLEANFILES = $(man_MANS) all: all-recursive .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/Lire/UI/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/Lire/UI/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man3: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list=''; test -n "$(man3dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } install-allperllibDATA: $(allperllib_DATA) @$(NORMAL_INSTALL) test -z "$(allperllibdir)" || $(MKDIR_P) "$(DESTDIR)$(allperllibdir)" @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(allperllibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(allperllibdir)" || exit $$?; \ done uninstall-allperllibDATA: @$(NORMAL_UNINSTALL) @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(allperllibdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(allperllibdir)" && rm -f $$files # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-recursive all-am: Makefile $(MANS) $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-allperllibDATA install-man install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man3 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-allperllibDATA uninstall-man uninstall-man: uninstall-man3 .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \ ctags-recursive install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am check-local clean clean-generic \ ctags ctags-recursive distclean distclean-generic \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-allperllibDATA install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man3 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-allperllibDATA uninstall-am uninstall-man \ uninstall-man3 .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lire-2.1.1/all/lib/Lire/UI/CompoundWidget.pm0000644000175000017500000001345010460672573015420 00000000000000package Lire::UI::CompoundWidget; use strict; use base qw/ Curses::UI::Container Lire::UI::Widget /; use Carp; use Curses; use Curses::UI::Common; use Locale::TextDomain 'lire'; use Lire::Utils qw/ check_object_param max/; use vars qw/ @CARP_NOT %bindings %routines /; @CARP_NOT = qw/ Curses::UI::Container /; %bindings = ( KEY_PPAGE() => 'pageup', KEY_NPAGE() => 'pagedown' ); %routines = ( 'pageup' => \&help_pageup, 'pagedown' => \&help_pagedown ); sub new { my $class = shift; my %userargs = @_; keys_to_lowercase(\%userargs); check_object_param( $userargs{'value'}, 'value', 'Lire::Config::Dictionary' ); my $self = $class->Curses::UI::Container::new( %userargs, '-bindings' => \%bindings, '-routines' => \%routines ); if ( $self->shown_components() ) { $self->_setup_value_widgets(); $self->_setup_help_viewer(); } else { $self->_setup_empty_label(); } $self->layout(); return $self; } sub _setup_empty_label { my $self = $_[0]; $self->add('empty_label', 'Label', '-text'=>__('-- This option does not have any attributes --')); return; } sub _setup_value_widgets { my $self = $_[0]; foreach my $comp ( $self->shown_components() ) { my $name = $comp->name(); $self->add( "${name}_label", 'Label', '-text' => $name, '-bold' => 1, '-textalignment' => 'right' ); $self->add( "${name}_widget", 'Lire::UI::Widget', 'value' => $self->{'value'}->get( $name ), '-onfocus' => \&_child_focus_cb, 'onvaluechanged' => sub { $self->run_event( 'onvaluechanged' ) }, ); } return; } sub shown_components { my $self = $_[0]; grep { ! $_->obsolete() } $self->{'value'}->spec()->components(); } # FIXME: this is hackish sub _help_onfocus_cb { my $help = $_[0]; my $self = $help->parent(); if ( $help->{'_tag'} ) { $self->focus_next(); $help->{'_tag'} = 0; } else { $self->parent()->focus_next(); $help->{'_tag'} = 1; } return; } sub _setup_help_viewer { my $self = $_[0]; return unless $self->shown_components(); $self->add( 'help_summary', 'Label', '-bold' => 1 ); my $viewer = $self->add( 'help_viewer', 'TextViewer', '-wrapping' => 1, '-vscrollbar' => 1, '_tag' => 0 ); $viewer->onFocus( \&_help_onfocus_cb ); return; } sub help_viewer_width { return int( ($_[0]->canvaswidth() - 2) * 0.4 ); } sub layout_value_widgets { my $self = $_[0]; $self->{'_label_width'} = $self->_max_label_size(); $self->{'_widget_width'} = ( $self->canvaswidth() - $self->{'_label_width'} - $self->help_viewer_width() - 2 ); my $y = 0; my $left = $self->shown_components(); if ( $left * 2 - 1> $self->canvasheight() ) { $Curses::UI::screen_too_small++; return; } foreach my $comp ( $self->shown_components() ) { my $label = $self->getobj( $comp->name() . '_label' ); $label->{'-x'} = 0; $label->{'-y'} = $y; $label->{'-width'} = $self->{'_label_width'}; my $widget = $self->getobj( $comp->name() . "_widget" ); $widget->{'-x'} = $self->{'_label_width'} + 1; $widget->{'-y'} = $y; $widget->{'-width'} = $self->{'_widget_width'}; $widget->{'-height'} = int( ($self->canvasheight() - $y - ($left - 1)) / $left ); $widget->layout(); $y += $widget->{'-height'} + 1; $left--; } return; } sub layout_help_viewer { my $self = $_[0]; my $help_width = $self->help_viewer_width(); my $x = $self->{'_label_width'} + $self->{'_widget_width'} + 2; my $summary = $self->getobj( 'help_summary' ); $summary->{'-x'} = $x; $summary->{'-y'} = 0; $summary->{'-width'} = $help_width; my $viewer = $self->getobj( 'help_viewer' ); $viewer->{'-x'} = $x; $viewer->{'-y'} = 2; $viewer->{'-width'} = $help_width; return; } sub layout_contained_objects { my $self = $_[0]; return $self unless $self->getobj( 'help_viewer' ); $self->layout_value_widgets(); $self->layout_help_viewer(); return $self->SUPER::layout_contained_objects(); } sub refresh_view { my $self = $_[0]; foreach my $comp ( $self->shown_components() ) { my $name = $comp->name(); die "$name: $self" unless $self->isa( 'Lire::UI::CompoundWidget' ); $self->getobj( "${name}_widget" )->refresh_view(); } return; } sub _max_label_size { my $self = $_[0]; my $avail = int( ( $self->canvaswidth()-2 ) * 0.25 ); my @labels = map { $_->name() } $self->shown_components(); my $max = max( map { length $_ } @labels ); return ( $max < $avail ? $max : $avail ); } # Routines sub help_pageup { my $self = $_[0]; my $help_viewer = $self->getobj( 'help_viewer' ); $help_viewer->cursor_pageup(); $help_viewer->draw(); return; } sub help_pagedown { my $self = $_[0]; my $help_viewer = $self->getobj( 'help_viewer' ); $help_viewer->cursor_pagedown(); $help_viewer->draw(); return; } # callbacks sub _child_focus_cb { my $widget = $_[0]; my $self = $widget->parent(); my $value = $widget->{'value'}; $self->getobj( 'help_summary' )->text( $value->summary() ); my $help_viewer = $self->getobj( 'help_viewer' ); $help_viewer->cursor_up( undef, $help_viewer->{'-yscrpos'} ) if ( $help_viewer->{'-yscrpos'} > 1 ); $help_viewer->text( $value->text_description() || __( 'No help available.' ) ); return; } 1; lire-2.1.1/all/lib/Lire/UI/StringWidget.pm0000644000175000017500000000236010761271216015071 00000000000000package Lire::UI::StringWidget; use strict; use base qw/ Curses::UI::TextEntry Lire::UI::Widget /; use Curses::UI::Common; use Lire::Utils qw/ check_object_param /; use Carp; use vars qw/@CARP_NOT/; @CARP_NOT = qw/Curses::UI::Container/; sub new { my $class = shift; my %userargs = @_; keys_to_lowercase(\%userargs); check_object_param( $userargs{'value'}, 'value', 'Lire::Config::Scalar' ); my $regexp = $userargs{'value'}->spec()->valid_re(); return $class->Curses::UI::TextEntry::new( %userargs, '-height' => 1, '-sbborder' => 1, '-text' => $userargs{'value'}->get(), '-onchange' => \&_on_change_cb, '-regexp' => $regexp, ); } sub layout { my $self = $_[0]; $self->{'-height'} = 1; return $self->SUPER::layout(); } sub refresh_view { my $self = $_[0]; $self->text( $self->{'value'}->get() ); return; } sub _on_change_cb { my $self = $_[0]; $self->{'value'}->set( $self->{'-text'} ); $self->run_event( 'onvaluechanged' ); return; } 1; lire-2.1.1/all/lib/Lire/UI/ListWidget.pm0000644000175000017500000001717110460672573014553 00000000000000package Lire::UI::ListWidget; use strict; use base qw/ Curses::UI::Container Lire::UI::Widget /; use Carp; use Curses; use Curses::UI::Common; use Locale::TextDomain 'lire'; use Lire::Utils qw/ check_object_param text_for_width /; use Lire::UI::Utils qw/ layout_buttonbox /; use Lire::UI::ScalarListWidget; use Lire::UI::CompoundListWidget; use Lire::UI::PolyListWidget; use vars qw/@CARP_NOT/; @CARP_NOT = qw/Curses::UI::Container/; my %bindings = ( KEY_IC() => 'add-element', "\cc" => "copy-element", KEY_DC() => 'del-element', "J" => 'move-element-down', "K" => 'move-element-up', ); my %routines = ( 'add-element' => \&add_element, 'copy-element' => \©_element, 'move-element' => \&move_element, 'move-element-up' => \&move_element_up, 'move-element-down' => \&move_element_down, 'del-element' => \&del_element ); sub new { my $class = shift; my %userargs = @_; keys_to_lowercase(\%userargs); check_object_param( $userargs{'value'}, 'value', 'Lire::Config::List' ); my $spec = $userargs{'value'}->spec(); my @comp_names = $spec->component_names(); my $component = @comp_names ? $spec->get( $comp_names[0] ) : undef; if ( $class eq __PACKAGE__) { croak "'" . $spec->name() . "' should contain at least one component" unless $component; if ( @comp_names > 1 ) { return new Lire::UI::PolyListWidget( @_ ); } elsif ( $component->isa( 'Lire::Config::ScalarSpec' ) ) { return new Lire::UI::ScalarListWidget( @_ ); } else { return new Lire::UI::CompoundListWidget( @_ ); } } my %userlistargs = (); foreach my $p ( qw/-title -titlereverse -titlefullwidth / ) { if ( exists $userargs{$p} ) { $userlistargs{$p} = $userargs{$p}; delete $userargs{$p}; } } my $self = $class->Curses::UI::Container::new( %userargs, 'component' => $component, '-bindings' => {%bindings}, '-routines' => {%routines}, '-releasefocus' => 1, ); my $list_widget = $self->add( 'list', 'Listbox', %userlistargs, '-onselchange' => \&_sel_change_cb, '-vscrollbar' => 1, '-border' => 1, '-selected' => 0 ); $self->refresh_view(); $self->add_contained_widgets(); $self->layout(); return $self; } sub extra_widget_height { return 0; } sub layout_contained_objects { my $self = $_[0]; return $self unless $self->getobj( 'list' ); my $list = $self->getobj( 'list' ); $list->{'-width'} = $self->canvaswidth(); $list->{'-height'} = $self->canvasheight() - $self->extra_widget_height() - 1; $list->{'-title'} = text_for_width( $self->title(), $self->canvaswidth() - 4 ) if ( $self->title() ); $self->layout_buttons(); return $self->SUPER::layout_contained_objects(); } sub layout_buttons { my $self = $_[0]; my $buttons = $self->getobj( 'buttons' ); $buttons->{'-buttons'}[0]{'-label'} = __( 'Add' ); $buttons->{'-buttons'}[2]{'-label'} = __( 'Copy' ); $buttons->{'-buttons'}[3]{'-label'} = __( 'Delete' ); $buttons->{'-buttons'}[4]{'-label'} = __( 'Up' ); $buttons->{'-buttons'}[5]{'-label'} = __( 'Down' ); layout_buttonbox( $self, $buttons, 1, 1 ); $buttons->{'-y'} = $self->canvasheight() - 1; return; } sub add_contained_widgets { my $self = $_[0]; $self->add_buttons_widget(); return; } sub add_buttons_widget { my $self = $_[0]; $self->add( 'buttons', 'Buttonbox', '-releasefocus' => 1, '-buttons' => [ { '-label' => __( 'Add' ), '-onpress' => sub { $self->do_routine( 'add-element' ) } }, { '-label' => __( 'Copy' ), '-onpress' => sub { $self->do_routine( 'copy-element' ) } }, { '-label' => __( 'Delete' ), '-onpress' => sub { $self->do_routine( 'del-element' ) } }, { '-label' => __( 'Up' ), '-onpress' => sub { $self->do_routine( 'move-element-up' ) } }, { '-label' => __( 'Down' ), '-onpress' => sub { $self->do_routine( 'move-element-down' ) } }, ] ); return; } sub title { return shift->getobj( 'list' )->title( @_ ); } # Routines sub add_element { my $self = $_[0]; my $instance = $self->new_value(); if ( $instance ) { my $list = $self->getobj( 'list' ); $self->{'value'}->append( $instance, $list->{'-selected'} ); $list->{'-ypos'} = ( defined $list->{'-selected'} ? $list->{'-selected'} + 1 : 0 ); $self->refresh_view(); $self->run_event( 'onvaluechanged' ); } return; } sub copy_element { my $self = $_[0]; my $list = $self->getobj( 'list' ); return unless defined $list->{'-selected'}; my $instance = $self->{'value'}->get( $list->{'-selected'} )->clone(); $self->{'value'}->append( $instance, $list->{'-selected'} ); $list->{'-ypos'} = $list->{'-selected'} + 1; $self->refresh_view(); $self->run_event( 'onvaluechanged' ); return; } sub move_element_up { $_[0]->move_element( -1 ); return; } sub move_element_down { $_[0]->move_element( 1 ); return; } sub move_element { my ( $self, $offset ) = @_; my $list = $self->getobj( 'list' ); return unless defined $list->{'-selected'}; my $new_idx = $list->{'-selected'} + $offset; $new_idx = 0 if $new_idx < 0; $new_idx = $#{$list->{'-values'}} if $new_idx > $#{$list->{'-values'}}; return if $new_idx == $list->{'-selected'}; $self->{'value'}->move( $list->{'-selected'}, $new_idx ); $list->{'-ypos'} = $new_idx; $self->refresh_view(); $self->run_event( 'onvaluechanged' ); return; } sub refresh_view { my $self = $_[0]; my $list_widget = $self->getobj( 'list' ); my $values = [ $self->{'value'}->elements() ]; my %labels = map { $_, $_->as_label() } $self->{'value'}->elements(); if ( scalar @$values == 0 ) { $values = [ __( '-- empty list --' ) ]; $list_widget->focusable( 0 ); $list_widget->{'-selected'} = undef; } else { $list_widget->focusable( 1 ); $list_widget->{'-selected'} = $list_widget->{'-ypos'}; } $list_widget->{'-values'} = $values; $list_widget->{'-labels'} = \%labels; $list_widget->draw(); return; } sub del_element { my $self = $_[0]; my $list_widget = $self->getobj( 'list' ); return unless $list_widget->focusable(); $self->{'value'}->remove( $list_widget->{'-ypos'} ); my $nbr = scalar $self->{'value'}->elements() - 1; if ( $list_widget->{'-selected'} > $nbr ) { $list_widget->{'-ypos'} = $nbr; } $self->refresh_view(); $self->run_event( 'onvaluechanged' ); return; } sub _sel_change_cb { my $list_widget = $_[0]; $list_widget->{'-selected'} = $list_widget->{'-ypos'}; $list_widget->run_event( '-onchange' ); return; } 1; lire-2.1.1/all/lib/Lire/UI/Utils.pm0000644000175000017500000001077610460673260013572 00000000000000package Lire::UI::Utils; use strict; use base qw/ Exporter /; use Carp; use Lire::Utils qw/ check_param check_object_param /; use vars qw( @EXPORT_OK ); BEGIN { @EXPORT_OK = qw/ button_box_width button_label layout_buttonbox /; } =pod =head1 NAME Lire::UI::Utils - Utility functions for UI management =head1 SYNOPSIS use Lire::UI::Utils; =head1 DESCRIPTION Utility functions for UI code. =head2 button_box_width( $buttons ) Computes the width required to draw the button box described by the 'buttons' parameter. This parameter is a hash reference. =cut sub button_box_width { my $buttons = $_[0]; check_object_param( $buttons, 'buttons', 'ARRAY' ); my $width = scalar ( @$buttons ) - 1; foreach my $button ( @$buttons ) { $width += length( $button->{'-label'} ); } return $width; } =pod =head2 button_label( $label, $max_button_width ) Returns a label suitable for a button considering that the maximum width of the button is $max_button_width. =cut sub button_label { my ( $label, $max_width ) = @_; check_param( $label, 'label' ); return '[' . $label . ']' if ! $max_width || (length( $label) + 2) <= $max_width; $max_width = 4 if $max_width < 4; return '[' . substr( $label, 0, $max_width-3) . '.]'; } =pod =head2 layout_buttonbox( $container, $box, [ $padleft ], [ $padright ] ) Crops the labels of the Curses::UI::Buttonbox $box until it fits in the canvaswidth() of the $container. $padleft and $padright can be used to allow space for padding. The function will set the '-width' and '-x' attributes of the Buttonbox. In the worst case, the label will be reduced to their first letter. The Buttonbox's buttons should have their '-label' attribute set to the full label without any button decorations (like '['), these will be added by the function after cropping. =cut sub layout_buttonbox { my ( $container, $box, $padleft, $padright ) = @_; check_object_param( $container, 'container', 'Curses::UI::Container' ); check_object_param( $box, 'buttonbox', 'Curses::UI::Buttonbox' ); $padleft ||= 0; $padright ||= 0; my $avail = $container->canvaswidth() - $padleft - $padright; # [] are added after the fact. my $n = @{$box->{'-buttons'}}; my $decorations = $n * 2; # We can reduce buttons to [X] my $min = $n * 3 + ( $n - 1 ); my $needed = button_box_width( $box->{'-buttons'} ) + $decorations; if ( $min <= $avail ) { while ( $needed > $avail ) { # Crop largest label my $max = max_label_idx( $box ); my $label = $box->{'-buttons'}[$max]{'-label'}; my $label_len = length $label; last if $label_len == 1; # All labels are at 1 char. if ( length $label == 2 ) { $label = substr( $label, 0, 1 ); } else { $label = substr( $label, 0, $label_len - 2 ) . '.'; } $box->{'-buttons'}[$max]{'-label'} = $label; $needed = button_box_width( $box->{'-buttons'} ) + $decorations; } } # Otherwise don't bother $box->{'-width'} = $needed; $box->{'-x'} = $padleft; # Add decorations foreach my $btn ( @{$box->{'-buttons'}} ) { $btn->{'-label'} = '[' . $btn->{'-label'} . ']'; } return; } sub max_label_idx { my $box = $_[0]; my $max_idx; my $max_len = 0; foreach ( my $i=0; $i < @{$box->{'-buttons'}}; $i++ ) { my $len = length $box->{'-buttons'}[$i]{'-label'}; if ( $len > $max_len ) { $max_len = $len; $max_idx = $i; } } return $max_idx; } 1; __END__ =pod =head1 SEE ALSO Lire::UI(3pm) =head1 VERSION $Id: Utils.pm,v 1.7 2006/07/23 13:16:32 vanbaal Exp $ =head1 AUTHORS Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/UI/CompoundListWidget.pm0000644000175000017500000000314110460672573016250 00000000000000package Lire::UI::CompoundListWidget; use strict; use base qw/ Lire::UI::ListWidget /; use Curses; use Curses::UI::Common; use Locale::TextDomain 'lire'; sub new { my $class = shift; my $self = $class->SUPER::new( @_ ); $self->set_routine( 'edit-element', \&edit_element ); $self->getobj( 'list' )->set_binding( sub { $self->do_routine( 'edit-element' ) }, KEY_ENTER() ); return $self; } # List API sub add_buttons_widget { my $self = $_[0]; $self->SUPER::add_buttons_widget(); my $buttons = $self->getobj( 'buttons' ); splice @{$buttons->{'-buttons'}}, 1, 0, { '-label' => __( 'Edit' ), '-onpress' => sub { $self->do_routine( 'edit-element' ) } }; return; } sub layout_buttons { my $self = $_[0]; $self->getobj( 'buttons' )->{'-buttons'}[1]{'-label'} = __( 'Edit' ); $self->SUPER::layout_buttons(); return; } sub new_value { my $self = $_[0]; my $new_instance = $self->{'component'}->instance(); return $new_instance if $self->root()->userdata()->edit_value_dialog( $new_instance ); return undef; } # Routines sub edit_element { my $self = $_[0]; my $list_widget = $self->getobj( 'list' ); return unless $list_widget->{'-focusable'}; my $instance = $list_widget->get(); my $new_instance = $instance->clone(); if ( $self->root()->userdata()->edit_value_dialog( $new_instance ) ) { $self->{'value'}->set( $list_widget->{'-selected'}, $new_instance ); $self->refresh_view(); $self->run_event( 'onvaluechanged' ); } return; } 1; lire-2.1.1/all/lib/Lire/UI/XMLSpecListWidget.pm0000644000175000017500000000453510460672574015750 00000000000000package Lire::UI::XMLSpecListWidget; use strict; use base qw/ Lire::UI::PolyListWidget /; use Curses::UI::Common qw/keys_to_lowercase/; use Lire::ReportSpec; use Lire::Config::XMLSpecListSpec; use Lire::Utils qw/check_object_param/; use Carp; sub new { my ( $class, %userargs ) = @_; keys_to_lowercase( \%userargs ); my $value = $userargs{'value'}; check_object_param( $value, 'value', 'Lire::Config::List' ); croak "'value' parameter's spec should be a 'Lire::Config::XMLSpecListSpec' instance, not '", $value->spec(), "'" unless $value->spec()->isa( 'Lire::Config::XMLSpecListSpec' ); my $self = $class->SUPER::new( %userargs ); $self->set_routine( 'edit-element', \&edit_element ); return $self; } sub superservice_filter { my ( $self, $superservice ) = @_; if ( @_ == 2 ) { $self->{'superservice'} = $superservice; $self->update_type_popupmenu(); $self->getobj( 'type_widget' )->draw(1); } return $self->{'superservice'}; } sub update_type_popupmenu { my $self = $_[0]; my $popup = $self->getobj( 'type_widget' ); if ( $self->{'superservice'} ) { my $rx = qr/^$self->{'superservice'}:(.*)/; my @values = (); foreach my $spec_id ( $self->{'value'}->spec()->component_names() ) { my ($type) = $spec_id =~ /$rx/; next unless $type; push @values, $type; } $popup->{'-values'} = [ sort @values ]; } else { $popup->{'-values'} = []; } $popup->{'-labels'} = {}; return; } sub new_value { my $self = $_[0]; return undef unless $self->{'superservice'}; my $type = $self->getobj( 'type_widget' )->get(); return undef unless defined $type; return $self->{'value'}->spec()->get( "$self->{'superservice'}:$type" )->instance(); } sub edit_element { my $self = $_[0]; my $list_widget = $self->getobj( 'list' ); return unless $list_widget->{'-focusable'}; my $info; if ( $self->{'value'}->spec()->type() eq 'reports' ) { my ( $super, $type ) = $list_widget->get()->name() =~ /$Lire::Config::XMLSpecListSpec::NAME_RE/; $info = Lire::ReportSpec->load( $super, $type )->create_table_info(); $info->set_variables_indices(); } $self->SUPER::edit_element(); $info->reset_variables_indices() if $info; return; } 1; lire-2.1.1/all/lib/Lire/UI/BoolWidget.pm0000644000175000017500000000251010460672573014522 00000000000000package Lire::UI::BoolWidget; use strict; use base qw/ Curses::UI::Radiobuttonbox Lire::UI::Widget /; use Carp; use Curses::UI::Common; use Locale::TextDomain 'lire'; use Lire::Utils qw/ check_object_param /; use vars qw/@CARP_NOT/; @CARP_NOT = qw/Curses::UI::Container/; sub new { my $class = shift; my %userargs = @_; keys_to_lowercase(\%userargs); check_object_param( $userargs{'value'}, 'value', 'Lire::Config::Scalar' ); my %args = ( %userargs, '-height' => 2, '-values' => [ __('yes'), __('no') ], '-onchange' => \&_on_change_cb, ); my $self = $class->Curses::UI::Radiobuttonbox::new( %args ); $self->refresh_view(); return $self; } sub layout { my $self = $_[0]; $self->{'-height'} = 2; return $self->SUPER::layout(); } sub refresh_view { my $self = $_[0]; # We don't want to use as_value() which will generate a # warning when the value is undef. my $bool = $self->{'value'}->spec()->normalize( $self->{'value'}->get() ); $self->{'-selected'} = ( $bool ? 0 : 1 ); $self->intellidraw(); return; } sub _on_change_cb { my $self = $_[0]; $self->{'value'}->set( ! $self->{'-selected'} ); $self->run_event( 'onvaluechanged' ); return; } 1; lire-2.1.1/all/lib/Lire/UI/PluginWidget.pm0000644000175000017500000000707210460672573015075 00000000000000package Lire::UI::PluginWidget; use strict; use base qw/ Curses::UI::Container Lire::UI::Widget /; use Curses::UI::Common; use Locale::TextDomain 'lire'; use Lire::Utils qw/ item_index check_param check_object_param /; use Lire::UI::Utils qw/ button_box_width /; use Carp; use vars qw/@CARP_NOT/; @CARP_NOT = qw/Curses::UI::Container/; sub new { my $class = shift; my %userargs = @_; keys_to_lowercase(\%userargs); check_object_param( $userargs{'value'}, 'value', 'Lire::Config::Plugin' ); my $self = $class->Curses::UI::Container::new( %userargs, '-height' => 1, '-releasefocus' => 1 ); my @options = map { $_->name() } $self->{'value'}->spec()->options(); my ( $selected, $focusable ); if ( @options ) { my $plugin = $self->{'value'}->get_plugin(); $selected = ( defined $plugin ? item_index( \@options, $plugin ) : undef ); $focusable = 1; } else { @options = ( __( '-- empty list --' ) ); $selected = 0; $focusable = 0; } $self->add( 'list', 'Popupmenu', '-onchange' => sub { $self->_on_change_cb_helper() }, '-selected' => $selected, '-values' => \@options, '-focusable' => $focusable ); $self->_update_button(); $self->layout(); return $self; } sub layout { my $self = $_[0]; $self->{'-height'} = 1; return $self->SUPER::layout(); } sub layout_contained_objects { my $self = $_[0]; my $list = $self->getobj( 'list' ); return $self unless $list; if ( $self->{'value'}->has_properties() ) { $list->{'-width'} = $self->canvaswidth() - 6; my $btn = $self->getobj( 'button' ); $btn->{'-x'} = $list->{'-width'} + 1; } else { $list->{'-width'} = $self->canvaswidth(); } return $self->SUPER::layout_contained_objects(); } sub _update_button { my $self = $_[0]; my $has_props = $self->{'value'}->has_properties(); my $button = $self->getobj( 'button' ); if ( !$button && $has_props) { $self->add( 'button', 'Buttonbox', '-buttons' => [ { '-label' => '<...>', '-onpress' => sub { $self->_properties_cb_helper() } } ], '-width' => 5 ); $self->layout(); $self->intellidraw(); } elsif ( $button && !$has_props ) { $self->delete( 'button' ); $self->layout(); $self->intellidraw(); } } sub _on_change_cb_helper { my $self = $_[0]; my $list = $self->getobj( 'list' ); $self->{'value'}->set_plugin( $list->get() ); $self->_update_button(); $self->run_event( 'onvaluechanged' ); return; } sub _properties_cb_helper { my $self = $_[0]; my $plugin = $self->{'value'}->get_plugin(); return unless ( defined $plugin && $self->{'value'}->has_properties() ); my $properties = $self->{'value'}->get_properties(); my $new_props = $properties->clone(); my $title = __x( 'Properties for {plugin}', 'plugin' => $plugin ); if ( $self->root()->userdata()->edit_value_dialog( $new_props, $title ) ) { my @comps = map { $_->name() } $new_props->spec()->components(); foreach my $comp ( @comps ) { $properties->set( $new_props->get( $comp ) ); } $self->run_event( 'onvaluechanged' ); } return; } 1; lire-2.1.1/all/lib/Lire/UI/DirectoryWidget.pm0000644000175000017500000000066210460672573015601 00000000000000package Lire::UI::DirectoryWidget; use strict; use base qw/ Lire::UI::FileWidget /; use Locale::TextDomain 'lire'; sub invalid_label_str { return __( 'Invalid directory' ); } sub browse_dialog { my $self = $_[0]; my $file_field = $self->getobj( 'file_field' ); return $self->root()->dirbrowser( '-title' => __( 'Select a Directory'), '-path' => $file_field->get() ); } 1; lire-2.1.1/all/lib/Lire/Test/0000755000175000017500000000000011677607767012627 500000000000000lire-2.1.1/all/lib/Lire/Test/TestCase.pm0000644000175000017500000001655510460673260014610 00000000000000package Lire::Test::TestCase; use strict; use base qw/ Test::Unit::TestCase /; use POSIX qw/ setlocale LC_MESSAGES tzset /; use File::Basename qw/ dirname /; use Cwd 'realpath'; use Test::Unit::Failure; use Test::Unit::Error; use Lire::Config; use Lire::Config::SpecParser; use Lire::Test::HashConfig; use Lire::PluginManager; use Lire::Utils qw/check_param/; =pod =head1 NAME Lire::Test::TestCase - Common base for Lire test cases. =head1 SYNOPSIS use base qw/Lire::Test::TestCase/; sub set_up { my $self = shift->SUPER::set_up(); $self->{'cfg'}{'lr_schemas_path'} = [ $self->{'tmpdir'} ]; } =head1 DESCRIPTION This package can be used to write test cases for Lire instead of inheriting directly from Test::Unit::TestCase. The default set_up method will create a Lire::Test::HashConfig object and set it up in the configuration framework. This makes it easy to set configuration variables to arbitrary values in the set_up() method. It also sets the LC_MESSAGES locale category to 'C'. If you override set_up() and tear_down() be sure to call the SUPER:: implementation. This subclass also defined a new kind of assertion which make sure that a snippet of code died with a proper error message. =head2 assert_died( $test, $regex, [ $msg ] ) Execute $test and fail unless it dies with a message matching $regex. $test should be a reference to CODE. $regex should be a Regexp ref. =head2 assert_dies( $regex, $test, [ $msg ] ) Like assert_died() but with a signature closer to the one defined in Test::Unit::Assert. =head2 assert_isa( $class, $instance, [ $msg ] ) Fails unless $instance is an instance of $class. =head1 FIXTURE RELATED METHOD =head2 lire_default_config_spec() Returns a Lire::Config::ConfigSpec object initialized from the default Lire configuration specification. =head2 set_up_tz( $tz ) When you tests uses timelocal() or localtime(), you should use that method to specify the TZ under which it should run. The TZ will be reset to its previous value during tear_down(). =head2 set_up_plugin_mgr() This will make the global PluginManager an instance that will only live for the current test. The old PluginManager will be reinstated during tear_down(). This way, you do not need to track calls to register_plugin(). =head1 SEE ALSO Test::Unit::TestCase(3pm) =head1 VERSION $Id: TestCase.pm,v 1.17 2006/07/23 13:16:32 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2003, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut sub set_up { my $self = $_[0]; $self->{'_saved_cfg'} = $Lire::Config::SINGLETON; $self->{'cfg'} = new Lire::Test::HashConfig( {} ); $Lire::Config::SINGLETON = $self->{'cfg'}; $self->{'_old_lc_messages'} = setlocale( LC_MESSAGES ); setlocale( LC_MESSAGES, 'C' ); return $self; } sub tear_down { my $self = $_[0]; $Lire::Config::SINGLETON = $self->{'_saved_cfg'}; setlocale( LC_MESSAGES, $self->{'_old_lc_messages'} ); $self->_tear_down_tz(); $self->_tear_down_plugin_mgr(); return $self; } sub set_up_tz { my ( $self, $tz ) = @_; check_param( $tz, 'tz' ); $self->{'_old_tz'} = $ENV{'TZ'} unless defined $self->{'_old_tz'}; $ENV{'TZ'} = $tz; tzset(); return; } sub _tear_down_tz { my $self = $_[0]; return unless defined $self->{'_old_tz'}; $ENV{'TZ'} = $self->{'_old_tz'} || ''; tzset(); $self->{'_old_tz'} = undef; return; } sub set_up_plugin_mgr { my $self = $_[0]; unless ( defined $self->{'_old_plugin_mgr'} ) { $self->{'_old_plugin_mgr'} = $Lire::PluginManager::instance; $Lire::PluginManager::instance = new Lire::PluginManager(); } return; } sub _tear_down_plugin_mgr { my $self = $_[0]; if ( defined $self->{'_old_plugin_mgr'} ) { $Lire::PluginManager::instance = $self->{'_old_plugin_mgr'}; $self->{'_old_plugin_mgr'} = undef; } return; } my $default_spec = undef; sub lire_default_config_spec { my $self = $_[0]; return $default_spec if defined $default_spec; my $dir = realpath( dirname( __FILE__ ) . '/../../config-spec' ); my $parser = new Lire::Config::SpecParser(); $parser->merge_specification( $dir . '/lire.xml' ); return $default_spec = $parser->configspec(); } sub assert_isa { my ( $self, $class, $instance, $msg ) = @_; $self->_error( "missing 'class' parameter" ) unless defined $class; $self->_error( "missing 'instance' parameter" ) unless @_ > 2; $self->_fail( defined $msg ? $msg : "expected a '$class' instance, got undef" ) unless defined $instance; $self->_fail( defined $msg ? $msg : "expected a '$class' instance, got unblessed '$instance'" ) unless ref $instance; $self->_fail( defined $msg ? $msg : ( "expected a '$class' instance, got a '" . ref( $instance ) . "' instance" ) ) unless UNIVERSAL::isa( $instance, $class ); } sub assert_dies { my ( $self, $regex, $test, $msg ) = @_; $self->assert_died( $test, $regex, $msg ); } sub assert_died { my ( $self, $test, $regex, $msg ) = @_; $self->_error( "missing 'test' parameter" ) unless defined $test; $self->_error( "missing 'regex' parameter" ) unless defined $regex; $self->_error( "'test' parameter should be a CODE reference" ) unless ref $test eq 'CODE'; $self->_error( "'regex' parameter should be a Regexp reference" ) unless ref $regex eq 'Regexp'; eval { $test->() }; $self->_fail( defined $msg ? $msg : "expected test to die" ) unless $@; $self->_fail( defined $msg ? $msg : "expected die message to match $regex, got '$@'" ) unless $@ =~ /$regex/; } sub _caller { my $self = $_[0]; my $level = 2; my ( $asserter, $file, $line ) = caller( $level ); while ( $file eq __FILE__ ) { $level++; ( $asserter, $file, $line ) = caller( $level ); } return ( $asserter, $file, $line ); } sub _fail { my $self = shift; my ( $asserter, $file, $line ) = $self->_caller(); my $message = join '', @_; Test::Unit::Failure->throw( '-text' => $message, '-object' => $self, '-file' => $file, '-line' => $line ); } sub _error { my $self = shift; my( $asserter, $file, $line ) = $self->_caller(); my $message = join '', @_; Test::Unit::Error->throw( '-text' => $message, '-object' => $self, '-file' => $file, '-line' => $line ); } 1; lire-2.1.1/all/lib/Lire/Test/DlfAnalyserTestCase.pm0000644000175000017500000001706410460673257016737 00000000000000package Lire::Test::DlfAnalyserTestCase; use strict; use base qw/ Lire::Test::TestCase /; use Lire::DlfSchema; use Lire::PluginManager; use Lire::Utils qw/file_content/; use Lire::ReportParser::AsciiDocBookFormatter qw/dbk2txt/; =pod =head1 NAME Lire::Test::DlfAnalyserTestCase - Base class for writing DlfAnalyser unit tests =head1 SYNOPSIS use base qw/ Lire::Test::DlfAnalyserTestCase /; use MyAnalyser; use File::Basename; sub create_analyser { return new MyAnalyser(); } sub schemasdir { return dirname( __FILE__ ) . "../.."; } sub registration_file { return dirname( __FILE__ ) . "../../myanalyser_init"; } =head1 DESCRIPTION This is a Test::Unit::TestCase subclass which can be used to easily write tests for DlfAnalyser. This class implements what is needed to provide the necessary fixture in the set_up() and tear_down(). It provides two base tests: test_api() and test_registration_file(). The test class needs to implement three methods to help complete the fixture. =head1 FIXTURES These are the methods that subclasses will usually override to provide the necessary data so that the DlfAnalyser test fixtures be setup. =head2 registration_file() This should return the script that is responsible for registring the analyser with the Lire::PluginManager. This is used by the default test_registration_file(). =cut sub registration_file { die "registration_file() unimplemented in ", ref $_[0], "\n"; } =pod =head2 schemasdir() This method should returns the directory which hold the schemas used by the analyser. This will be added to the lr_schemas_path configuration variable. =cut sub schemasdir { die "schemasdir() unimplemented in ", ref $_[0], "\n"; } =pod =head2 create_analyser() This should return an instance of the Lire::DlfAnalyser instance to test. =cut sub create_analyser { die "create_analyser() unimplemented in ", ref $_[0], "\n"; } sub tear_down { my $self = $_[0]; my $analyser = $self->create_analyser(); Lire::PluginManager->unregister_plugin( 'dlf_analyser', $analyser->name()) if Lire::PluginManager->has_plugin( 'dlf_analyser', $analyser->name()); $self->SUPER::tear_down(); return; } =pod =head1 Mock Converter Process =head2 create_mock_process( [ $store ]) This method will return a MockDlfAnalyserProcess which can be use to help test the DlfAnalyser. All values to write_dlf() and error(), are saved and can be queried through the dlf() and errors() methods. Note that the dlf() method returns an array reference of array reference. The first element in the inner arrays is the dlf and the other elements are the related DLF id, if any. The mock process analyser_instance() method which returns the DlfAnalyser created by create_analyser() and associated to its instance. The optional $store parameter should be a Lire::DlfStore instance that will be available through the dlf_store() method. =cut sub create_mock_process { my ( $self, $store ) = @_; return new Lire::Test::MockDlfAnalyserProcess( $self->create_analyser(), $store ); } =pod =head1 DEFAULT TESTS =head2 test_api() Make sure that all methods required by Lire::DlfAnalyser are implemented. It also tests that the src_schema() and dst_schema() are available. It checks that description() formats correctly as DocBook. =head2 test_registration_file() Checks that the registration script correctly registers the analyser with the PluginManager. =cut sub test_registration_file { my $self = $_[0]; $self->{'cfg'}{'lr_schemas_path'} = [ $self->schemasdir() ]; my $analyser = $self->create_analyser(); $self->error( "$analyser should be a Lire::DlfAnalyser" ) unless $analyser->isa( 'Lire::DlfAnalyser' ); eval file_content( $self->registration_file() ); $self->error( $@ ) if $@; $self->assert( Lire::PluginManager->has_plugin( 'dlf_analyser', $analyser->name() ), $analyser->name() . " wasn't registered" ); } sub test_api { my $self = $_[0]; $self->{'cfg'}{'lr_schemas_path'} = [ $self->schemasdir() ]; my $analyser = $self->create_analyser(); $self->error( "$analyser should be a Lire::DlfAnalyser" ) unless $analyser->isa( 'Lire::DlfAnalyser' ); $self->assert_not_null( $analyser->name(), "name() returned undef" ); $self->assert_not_null( $analyser->title(), "title() returned undef" ); my @warn = (); local $SIG{__WARN__} = sub { my $msg = join "", @_; push @warn, $msg; $self->annotate( $msg ) }; $self->assert_not_null( $analyser->description(), "description() returned undef" ); eval { dbk2txt( $analyser->description() ) }; $self->fail( "error while formatting description: $@" ) if $@; $self->assert( ! @warn, "there were DocBook warnings" ); $self->assert( Lire::DlfSchema->has_schema( $analyser->src_schema() ), "non-existent src_schema: " . $analyser->src_schema() ); $self->assert( Lire::DlfSchema->has_schema( $analyser->dst_schema() ), "non-existent dst_schema: " . $analyser->dst_schema() ); } package Lire::Test::MockDlfAnalyserProcess; use base qw/Lire::DlfAnalyserProcess/; use Lire::Utils qw/ check_param check_object_param /; sub new { my ( $class, $analyser, $store ) = @_; check_object_param( $analyser, 'analyser', 'Lire::DlfAnalyser' ); check_object_param( $store, 'store', 'Lire::DlfStore' ) if defined $store; my $self = bless { '_errors' => [], '_dlf' => [], '_analyser_instance' => $analyser, '_store' => $store, '_dlf_count' => 0, '_error_count' => 0, '_period' => 'all', }, $class; return $self; } sub write_dlf { my ( $self, $dlf, $related_tos ) = @_; check_object_param( $dlf, 'dlf', 'HASH' ); my $rec = [ { %$dlf } ]; push @$rec, @$related_tos if defined $related_tos; push @{$self->{'_dlf'}}, $rec; $self->{'_dlf_count'}++; return; } sub dlf { return $_[0]{'_dlf'}; } sub error { my ( $self, $error ) = @_; check_param( $error, 'error' ); push @{$self->{'_errors'}}, $error; $self->{'_error_count'}++; return; } sub errors { return $_[0]{'_errors'}; } sub analyser_instance { return $_[0]->{'_analyser_instance'}; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Test::TestCase(3pm), Lire::DlfAnalyser(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: DlfAnalyserTestCase.pm,v 1.3 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Test/PluginTestCase.pm0000644000175000017500000001132410460673260015754 00000000000000package Lire::Test::PluginTestCase; use strict; use base qw/ Lire::Test::TestCase /; use Lire::Config::SpecParser; use Lire::PluginManager; use Lire::Utils qw/file_content/; use Lire::ReportParser::AsciiDocBookFormatter qw/dbk2txt/; =pod =head1 NAME Lire::Test::PluginTestCase - Base class for writing Plugin unit tests =head1 SYNOPSIS use base qw/ Lire::Test::PluginTestCase /; use MyPlugin; use File::Basename; sub create_plugin { return new MyPlugin(); } sub registration_file { return dirname( __FILE__ ) . "../../plugin_init"; } =head1 DESCRIPTION This is a Test::Unit::TestCase subclass which can be used to easily write tests for Lire::Plugin. This class implements what is needed to provide the necessary fixture in the set_up() and tear_down(). It provides two base tests: test_api() and test_registration_file(). The test class needs to implement two methods to help complete the fixture. =head1 FIXTURES These are the methods that subclasses will usually override to provide the necessary data so that the ChartType test fixtures be setup. =head2 registration_file() This should return the script that is responsible for registring the analyser with the Lire::PluginManager. This is used by the default test_registration_file(). =cut sub registration_file { die "registration_file() unimplemented in ", ref $_[0], "\n"; } =pod =head2 properties_spec_file() If this method returns a filename, it will be set as the default configuration spec for the test. Use it when the plugin has properties. =cut sub properties_spec_file { return undef; } =pod =head2 create_plugin() This should return an instance of the Lire::Plugin instance to test. =cut sub create_plugin { die "create_() unimplemented in ", ref $_[0], "\n"; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->set_up_plugin_mgr(); my $spec_file = $self->properties_spec_file(); if ( $spec_file ) { my $parser = new Lire::Config::SpecParser(); $parser->merge_specification( $spec_file ); $self->{'cfg'}{'_lr_config_spec'} = $parser->configspec(); } return; } =pod =head1 DEFAULT TESTS =head2 test_api() Make sure that all methods required by Lire::Plugin are implemented. It checks that description() formats correctly as DocBook. =head2 test_registration_file() Checks that the registration script correctly registers the analyser with the PluginManager. =cut sub test_registration_file { my $self = $_[0]; my $plugin = $self->create_plugin(); $self->error( "$plugin should be a Lire::Plugin" ) unless $plugin->isa( 'Lire::Plugin' ); eval file_content( $self->registration_file() ); $self->error( $@ ) if $@; $self->assert( Lire::PluginManager->has_plugin( $plugin->type(), $plugin->name() ), $plugin->name() . " wasn't registered" ); } sub test_api { my $self = $_[0]; my $plugin = $self->create_plugin(); $self->error( "$plugin should be a Lire::Plugin" ) unless $plugin->isa( 'Lire::Plugin' ); $self->assert_not_null( $plugin->name(), "name() returned undef" ); $self->assert_not_null( $plugin->title(), "title() returned undef" ); my @warn = (); local $SIG{__WARN__} = sub { my $msg = join "", @_; push @warn, $msg; $self->annotate( $msg ) }; $self->assert_not_null( $plugin->description(), "description() returned undef" ); eval { dbk2txt( $plugin->description() ) }; $self->fail( "error while formatting description: $@" ) if $@; $self->assert( ! @warn, "there were DocBook warnings" ); } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Test::TestCase(3pm), Lire::Plugin(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: PluginTestCase.pm,v 1.2 2006/07/23 13:16:32 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Test/HashConfig.pm0000644000175000017500000000750710460673257015111 00000000000000package Lire::Test::HashConfig; use strict; use base qw/ Lire::Config /; use Carp; use Lire::Utils qw/ check_param /; =pod =head1 NAME Lire::Test::HashConfig - Braindead Lire::Config implementation =head1 SYNOPSIS use base qw/Test::Unit::TestCase/; use Lire::Test::HashConfig; sub set_up { my $self = $_[0]; $self->{'old_config'} = $Lire::Config::SINGLETON; $Lire::Config::SINGLETON = new Lire::Test::HashConfig( { 'lr_archive' => undef, } ); } =head1 DESCRIPTION This is a simple module which is meant to be used from the set_up() method in unit tests. It can be used to create a 'fake' configuration to provide known values to the module under test. The new() method takes an hash reference which contains the configuration variable. The only methods of the Lire::Config interface implemented are the get() and config_spec(). The get() method which will return exactly the values provided in the new() method. Trying to get other configuration variables will throw a 'No such configuration variable' exception (as if the variable wasn't defined in the schema). The config_spec() method will return the object associated with the '_lr_config_spec' key. It will throw an exception if this key wasn't set. All other Lire::Config methods will throw a 'Unimplemented method' exception. =head1 SEE ALSO Lire::Config(3pm), Test::Unit::TestCase(3pm) =head1 VERSION $Id: HashConfig.pm,v 1.9 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut sub new { my ( $pkg, $cfg ) = @_; check_param( $cfg, 'cfg', sub { ref $_[0] eq 'HASH' }, "'cfg' parameter should be a hash reference" ); return bless {%$cfg}, $pkg; } sub get { my ( $self, $name ) = @_; check_param( $name, 'name', sub { exists $self->{$_[0]} }, "No such configuration variable" ); return ( UNIVERSAL::isa( $self->{$name}, 'Lire::Config::Value' ) ? $self->{$name}->get() : $self->{$name} ); } sub get_var { my ( $self, $name ) = @_; my $value = $self->{$name}; return $value if UNIVERSAL::isa( $value, 'Lire::Config::Value' ); croak "'$name' isn't a Lire::Config::Value object and '_lr_config_spec' isn't set" unless defined $self->{'_lr_config_spec'}; return $self->{'_lr_config_spec'}->get( $name )->instance( 'value' => $value ); } sub config_spec { my $self = $_[0]; croak "attribute '_lr_config_spec' is undef" unless defined $self->{'_lr_config_spec'}; return $self->{'_lr_config_spec'}; } sub init { } BEGIN { no strict 'refs'; foreach my $method ( qw/config_spec_path add_config_spec_path_dir del_config_spec_path_dir config_files add_config_path add_config_file get_config_file del_config_file / ) { *{$method} = sub { die "Unimplemented method: $method()" }; } } 1; lire-2.1.1/all/lib/Lire/Test/CommandResult.pm0000644000175000017500000000521310460673257015645 00000000000000package Lire::Test::CommandResult; use strict; =pod =head1 NAME Lire::Test::CommandResult - Object used to report the results of shell commands =head1 SYNOPSIS use Lire::Test::FunctionalTestCase; my $result = $self->lire_run( "echo Test" ); print $result->status(); print $result->stdout(); print $result->stderr(); print scalar $result->sent_mail(), " emails were sent.\n"; =head1 DESCRIPTION Lire::Test::ComandResult objects are used to report the results of shell commands run through Lire::Test::FunctionalTestCase::lire_run(). =cut sub new { my $class = shift; return bless { @_ }, $class; } =pod =head2 command() Returns the shell command that was run. This is the complete command line which was interpreated by the shell. =cut sub command { return $_[0]{'_command'}; } =pod =head2 status() Returns the command result status. (What is usually contained in $?). =cut sub status { return $_[0]{'_status'}; } =pod =head2 stdout() Returns what was output on stdout while executing the command. =cut sub stdout { return $_[0]{'_stdout'}; } =pod =head2 stderr() Returns what was output on stderr while executing the command. =cut sub stderr { return $_[0]{'_stderr'}; } =pod =head2 sent_mail() Returns in an array reference the message that were sent out during this command run. The element of this array are hash reference containing two keys: =over =item recipients An array reference containing the recipients as passed on the command line to sendmail. =item message The email which was sent. This is the complete text of the email. This is what was passed to sendmail via STDIN. =back =cut sub sent_mail { return $_[0]{'_sent_mail'}; } 1; __END__ =pod =head1 SEE ALSO Lire::Test::FunctionaLTestCase(3pm) =head1 VERSION $Id: CommandResult.pm,v 1.6 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Test/Makefile.am0000644000175000017500000000321110076270175014555 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.9 2004/07/17 18:31:25 flacoste Exp $ ## Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org ## ## This file is part of Lire. ## ## Lire is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk allperllibdir = $(LR_PERL5LIBDIR)/Lire/Test allperllib_DATA = \ CommandResult.pm \ CursesUIDriver.pm \ DlfAnalyserTestCase.pm \ DlfConverterTestCase.pm \ FunctionalTestCase.pm \ HashConfig.pm \ Mock.pm \ PluginTestCase.pm \ TestCase.pm man_MANS = \ CommandResult.3pm \ CursesUIDriver.3pm \ DlfAnalyserTestCase.3pm \ DlfConverterTestCase.3pm \ FunctionalTestCase.3pm \ HashConfig.3pm \ Mock.3pm \ PluginTestCase.3pm \ TestCase.3pm perlpackage = Lire::Test transform = s,^,$(perlpackage)::, EXTRA_DIST = $(allperllib_DATA) CLEANFILES = $(man_MANS) lire-2.1.1/all/lib/Lire/Test/Makefile.in0000644000175000017500000004353011677606132014602 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/include/rules.mk subdir = all/lib/Lire/Test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(allperllib_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) transform = s,^,$(perlpackage)::, ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done allperllibdir = $(LR_PERL5LIBDIR)/Lire/Test allperllib_DATA = \ CommandResult.pm \ CursesUIDriver.pm \ DlfAnalyserTestCase.pm \ DlfConverterTestCase.pm \ FunctionalTestCase.pm \ HashConfig.pm \ Mock.pm \ PluginTestCase.pm \ TestCase.pm man_MANS = \ CommandResult.3pm \ CursesUIDriver.3pm \ DlfAnalyserTestCase.3pm \ DlfConverterTestCase.3pm \ FunctionalTestCase.3pm \ HashConfig.3pm \ Mock.3pm \ PluginTestCase.3pm \ TestCase.3pm perlpackage = Lire::Test EXTRA_DIST = $(allperllib_DATA) CLEANFILES = $(man_MANS) all: all-am .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/Lire/Test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/Lire/Test/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man3: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list=''; test -n "$(man3dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } install-allperllibDATA: $(allperllib_DATA) @$(NORMAL_INSTALL) test -z "$(allperllibdir)" || $(MKDIR_P) "$(DESTDIR)$(allperllibdir)" @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(allperllibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(allperllibdir)" || exit $$?; \ done uninstall-allperllibDATA: @$(NORMAL_UNINSTALL) @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(allperllibdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(allperllibdir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-allperllibDATA install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man3 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-allperllibDATA uninstall-man uninstall-man: uninstall-man3 .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ distclean distclean-generic distdir dvi dvi-am html html-am \ info info-am install install-allperllibDATA install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-man3 \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall \ uninstall-allperllibDATA uninstall-am uninstall-man \ uninstall-man3 .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lire-2.1.1/all/lib/Lire/Test/DlfConverterTestCase.pm0000644000175000017500000002033010460673257017116 00000000000000package Lire::Test::DlfConverterTestCase; use strict; use base qw/ Lire::Test::TestCase /; use Lire::DlfSchema; use Lire::PluginManager; use Lire::Utils qw/file_content/; use Lire::ReportParser::AsciiDocBookFormatter qw/dbk2txt/; =pod =head1 NAME Lire::Test::DlfConverterTestCase - Base class for writing DLfConverter unit tests =head1 SYNOPSIS use base qw/ Lire::Test::DlfConverterTestCase /; use MyConverter; use File::Basename; sub create_converter { return new MyConverter(); } sub schemasdir { return dirname( __FILE__ ) . "../.."; } sub registration_file { return dirname( __FILE__ ) . "../../myconverter_init"; } =head1 DESCRIPTION This is a Test::Unit::TestCase subclass which can be used to easily write tests for DlfConverter. This class implements what is needed to provide the necessary fixture in the set_up() and tear_down(). It provides two base tests: test_api() and test_registration_file(). The test class needs to implement three methods to help complete the fixture. =head1 FIXTURES These are the methods that subclasses will usually override to provide the necessary data so that the DlfConverter test fixtures be setup. =head2 registration_file() This should return the script that is responsible for registring the converter with the Lire::PluginManager. This is used by the default test_registration_file(). =cut sub registration_file { die "registration_file() unimplemented in ", ref $_[0], "\n"; } =pod =head2 schemasdir() This method should returns the directory which hold the schemas used by the converter. This will be added to the lr_schemas_path configuration variable if set_up_path() is called. =cut sub schemasdir { die "schemasdir() unimplemented in ", ref $_[0], "\n"; } =pod =head2 create_converter() This should return an instance of the Lire::DlfConverter instance to test. =cut sub create_converter { die "create_converter() unimplemented in ", ref $_[0], "\n"; } =pod =head2 set_up_path() This will add the schemasdir to the 'lr_schemas_path'. =cut sub set_up_path { my $self = $_[0]; $self->{'cfg'}{'lr_schemas_path'} = [ $self->schemasdir() ]; return; } sub tear_down { my $self = $_[0]; my $converter = $self->create_converter(); Lire::PluginManager->unregister_plugin( 'dlf_converter', $converter->name()) if Lire::PluginManager->has_plugin( 'dlf_converter', $converter->name()); $self->SUPER::tear_down(); return; } =pod =head1 Mock Converter Process =head2 create_mock_process() This method will return a MockDlfConverterProcess which can be use to help test the DlfConverter. All values to write_dlf(), error(), ignore_log_line() and save_log_line() are saved and can be queried through the dlf( 'schema' ), errors(), ignored() and saved() methods. The mock process also has a converter() method which returns the DlfConverter created by create_converter() and associated to its instance. =cut sub create_mock_process { my $self = $_[0]; return new Lire::Test::MockDlfConverterProcess( $self->create_converter() ); } =pod =head1 DEFAULT TESTS =head2 test_api() Make sure that all methods required by Lire::DlfConverter are implemented. It also tests that the schemas returned by schemas() are available. It checks that description() formats correctly as DocBook. =cut sub test_api { my $self = $_[0]; $self->set_up_path(); my $converter = $self->create_converter(); $self->error( "$converter should be a Lire::DlfConverter" ) unless $converter->isa( 'Lire::DlfConverter' ); $self->assert_not_null( $converter->name(), "name() returned undef" ); $self->assert_not_null( $converter->title(), "title() returned undef" ); my @warn = (); local $SIG{__WARN__} = sub { my $msg = join "", @_; push @warn, $msg; $self->annotate( $msg ) }; $self->assert_not_null( $converter->description(), "description() returned undef" ); eval { dbk2txt( $converter->description() ) }; $self->fail( "error while formatting description: $@" ) if $@; $self->assert( ! @warn, "there were DocBook warnings" ); my @schemas = $converter->schemas(); $self->assert_num_not_equals( 0, scalar @schemas ); foreach my $schema ( @schemas ) { $self->assert( Lire::DlfSchema->has_schema( $schema ), "non-existent schema: " . $schema ); } } =pod =head2 test_registration_file() Checks that the registration script correctly registers the converter with the PluginManager. =cut sub test_registration_file { my $self = $_[0]; $self->set_up_path(); my $converter = $self->create_converter(); $self->error( "$converter should be a Lire::DlfConverter" ) unless $converter->isa( 'Lire::DlfConverter' ); eval file_content( $self->registration_file() ); $self->error( $@ ) if $@; $self->assert( Lire::PluginManager->has_plugin( 'dlf_converter', $converter->name() ), $converter->name() . " wasn't registered" ); } package Lire::Test::MockDlfConverterProcess; use base qw/Lire::DlfConverterProcess/; use Lire::Utils qw/ check_param check_object_param /; use Carp; sub new { my ( $class, $converter ) = @_; check_object_param( $converter, 'converter', 'Lire::DlfConverter' ); my $self = bless { '_errors' => [], '_saved' => [], '_dlf' => {}, '_ignored' => [], '_converter' => $converter, }, $class; $self->_init_counters(); foreach my $schema ( $converter->schemas() ) { $self->{'_dlf'}{$schema} = []; } return $self; } sub write_dlf { my ( $self, $schema, $dlf ) = @_; check_param( $schema, 'schema' ); check_object_param( $dlf, 'dlf', 'HASH' ); croak "schema '$schema' wasn't defined by '", $self->{'_converter'}->name(), "' converter" unless exists $self->{'_dlf'}{$schema}; push @{$self->{'_dlf'}{$schema}}, { %$dlf }; $self->{'_dlf_count'}++; return; } sub dlf { my ( $self, $schema ) = @_; check_param( $schema, 'schema' ); croak "schema '$schema' wasn't defined by '", $self->{'_converter'}->name(), "' converter" unless exists $self->{'_dlf'}{$schema}; return $self->{'_dlf'}{$schema}; } sub error { my ( $self, $error, $line ) = @_; check_param( $error, 'error' ); push @{$self->{'_errors'}}, [ $error, $line ]; $self->{'_error_count'}++; return; } sub errors { return $_[0]{'_errors'}; } sub save_log_line { my ( $self, $line ) = @_; check_param( $line, 'line' ); push @{$self->{'_saved'}}, $line; $self->{'_saved_count'}++; return; } sub saved { return $_[0]{'_saved'}; } sub ignore_log_line { my ( $self, $line, $reason ) = @_; check_param( $line, 'line' ); push @{$self->{'_ignored'}}, [ $line, $reason ]; $self->{'_ignored_count'}++; return; } sub ignored { return $_[0]{'_ignored'}; } sub converter { return $_[0]{'_converter'}; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Test::TestCase(3pm), Lire::DlfConverter(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: DlfConverterTestCase.pm,v 1.20 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Test/FunctionalTestCase.pm0000644000175000017500000003657110460673257016641 00000000000000package Lire::Test::FunctionalTestCase; use strict; use base qw/ Test::Unit::TestCase /; use Carp; use File::Path qw/ mkpath rmtree /; use File::Copy; use File::Basename; use File::Path qw/rmtree/; use IO::Dir; use Lire::Config; use Lire::PluginManager; use Lire::Config::SpecParser; use Lire::Config::Value; use Lire::Config::Build qw/ ac_info ac_path /; use Lire::Test::CommandResult; use Lire::Utils qw/ tempdir create_file file_content check_param /; =pod =head1 NAME Lire::Test::FunctionalTestCase - Base class for writing functional unit tests =head1 SYNOPSIS use base qw/ Lire::Test::FunctionalTestCase/; =head1 DESCRIPTION This is a Test::Unit::TestCase subclass which can be used to make it easier to write functional tests. =head2 WHAT ARE FUNCTIONAL TESTS Unlike unit tests that test the semantics of the API and document the internals assumptions, functional tests are tests that tests the 'functionality' of the overall software. They kind of document the expected functionality of the software. =head2 Lire::Test::FunctionalTestCase In Lire, the "expected functionality" is exercised by running commands, so this module provides convenient methods to run Lire commands and tests their expected output. It also setup a mock sendmail which can be used to analyze the email that the Lire system should send. Some of Lire functionality cannot be tested anymore simply by running command (for example the Curses::UI based user interface cannot be tested that way but throught the use of Lire::Test::CursesUIDriver). For these kind of tests, this base class will set up a new Lire::Config and Lire::PluginManager instance in the set_up method. Tests that requires these functionality can simply call Lire::Config->init() and Lire::PluginManager->instance()->register_default_converters() without fear of messing the test environement. =cut sub new { my $self = shift->SUPER::new( @_ ); $self->{'_test_files'} = []; $self->{'_locale'} = 'C'; $self->_check_lire_installation(); $self->_load_config_spec(); return $self; } sub set_up { my $self = $_[0]; $self->{'_config_files'} = {}; $self->{'_rundir'} = tempdir( "FunctionalTest_XXXXXX" ); $self->{'_homedir'} = $self->{'_rundir'} . "/home"; mkdir $self->{'_homedir'} or croak "failed to create $self->{'_homedir'}"; $self->_create_lire_home_directories(); $self->_set_up_fake_sendmail(); $self->_set_up_lire_globals(); $self->{'_stdout_file'} = $self->{'_rundir'} . "/stdout.log"; $self->{'_stderr_file'} = $self->{'_rundir'} . "/stderr.log"; unshift @INC, ac_info( 'LR_PERL5LIB' ); return; } sub tear_down { my $self = $_[0]; foreach my $f ( @{$self->{'_test_files'}}) { unlink $f or croak "failed to delete $f"; } rmtree( $self->{'_rundir'} ); $self->_tear_down_lire_globals(); shift @INC if $INC[0] eq ac_info( 'LR_PERL5LIB' ); return; } sub _check_lire_installation { my $self = $_[0]; my $lr_xml2report = ac_info( 'bindir' ) . "/lr_xml2report"; my $defaults = ac_path( 'sysconfdir', 'PACKAGE' ) . "/defaults"; my $sysconfdir = ac_path( 'sysconfdir', 'PACKAGE' ); my $datadir = ac_path( 'datadir', 'PACKAGE' ); croak "$lr_xml2report isn't an executable. Was Lire installed?" unless -f $lr_xml2report && -x $lr_xml2report; croak "$defaults isn't present. Was Lire installed?" unless -f $defaults && -r $defaults; croak "you need write access to Lire's sysconfdir ($sysconfdir) to use FunctionalTestCase" unless -w $sysconfdir; croak "you need write access to Lire's datadir ($datadir) to use FunctionalTestCase" unless -w $datadir; } sub _create_lire_home_directories { my $self = $_[0]; mkpath( [ $self->{'_homedir'} . "/.lire", $self->{'_homedir'} . "/.lire/config", $self->{'_homedir'} . "/.lire/converters", $self->{'_homedir'} . "/.lire/plugins", $self->{'_homedir'} . "/.lire/schemas", $self->{'_homedir'} . "/.lire/filters", $self->{'_homedir'} . "/.lire/reports", ], 0, 0755 ) == 7 or croak "mkpath() failed"; return; } sub _set_up_lire_globals { my $self = $_[0]; $self->{'_old_homedir'} = $ENV{'HOME'}; $self->{'_old_config'} = $Lire::Config::SINGLETON; $self->{'_old_mgr'} = $Lire::PluginManager::instance; $ENV{'HOME'} = $self->{'_homedir'}; $Lire::Config::SINGLETON = new Lire::Config::XMLFilesConfig(); $Lire::PluginManager::instance = new Lire::PluginManager(); return; } sub _tear_down_lire_globals { my $self = $_[0]; $ENV{'HOME'} = $self->{'_old_homedir'}; $Lire::Config::SINGLETON = $self->{'_old_config'}; $Lire::PluginManager::instance = $self->{'_old_mgr'}; return; } sub _load_config_spec { my $self = $_[0]; my $parser = new Lire::Config::SpecParser(); $parser->merge_specifications_dir( ac_path( 'datadir', 'PACKAGE') . "/config-spec" ); $self->{'_spec'} = $parser->configspec(); return; } sub _set_up_sendmail_config { my $self = $_[0]; my $cfg = $self->create_test_cfg_file( "func_test_sendmail" ); $cfg->global->get( "sendmail_path" )->set( $self->{'_sendmail_path'} ); $cfg->save(); return; } sub _set_up_fake_sendmail { my $self = $_[0]; $self->{'_maildir'} = "$self->{'_rundir'}/.func_test_mail"; mkdir $self->{'_maildir'}, 0770 or croak "mkdir $self->{'_maildir'} failed: $!"; $self->{'_sendmail_path'} = "$self->{'_rundir'}/func_test_sendmail"; open my $fh, "> $self->{'_sendmail_path'}" or croak "open $self->{'_sendmail_path'} failed: $!"; my $script = <<'EOF'; #! PERL -w use strict; use File::Copy; use Carp; my $file; my $idx = 0; while (1) { $file = sprintf( 'MAILDIR/%02x', $idx); last unless -f "$file.recipients"; $idx++; } open RECIPIENTS, "> $file.recipients" or croak "open $file.recipients failed: $!\n"; print RECIPIENTS join( "\n", @ARGV ), "\n"; close RECIPIENTS; copy( \*STDIN, $file . ".message" ); exit 0 EOF my $perl = ac_info( 'PERL' ); $script =~ s/PERL/$perl/; $script =~ s/MAILDIR/$self->{'_maildir'}/g; print $fh $script; close $fh; chmod 0775, $self->{'_sendmail_path'} or croak "failed to chmod $self->{'_sendmail_path'}: $!\n"; $self->_set_up_sendmail_config(); return; } =pod =head2 homedir() Returns the directory which will be assigned to ENV{'HOME'} when commands are run. This directory is cleaned up after every test. =cut sub homedir { return $_[0]{'_homedir'}; } =pod =head2 rundir() Returns the directory which will be the working directory when the commands are run. This directory is cleaned up after every test. =cut sub rundir { return $_[0]{'_rundir'}; } =pod =head2 config_spec() Returns the Lire::Config::TypeSpec object which will be used at runtime by the functional tests. It can be used to setup configuration files for the test. =cut sub config_spec { return $_[0]{'_spec'}; } =pod =head2 locale( [new_locale] ) Changes the locale under which the functional test is going to be run. By default, all tests are run under the 'C' locale ignoring all user's environment variables. Returns the previous locale set. =cut sub locale { my ( $self, $locale ) = @_; my $old = $self->{'_locale'}; $self->{'_locale'} = $locale || 'C'; return $old; } =pod =head2 lire_run( $shell_cmd ) This method runs the command $shell_cmd through the shell and returns a Lire::Test::CommandResult object which can be used to run tests on this command. The Lire environment will be set up before invoking the shell. =cut sub lire_run { my ($self, $cmd) = @_; check_param( $cmd, 'cmd' ); rmtree( $self->{'_maildir'} ); mkdir $self->{'_maildir'}, 0770 or croak "mkdir $self->{'_maildir'} failed: $!"; $self->_create_cfg_files(); my $pid = fork; croak "fork failed: $!" unless defined $pid; if ( !$pid ) { $self->_run_command( $cmd ); } return $self->_make_cmd_result( $cmd, $pid ); } sub _run_command { my ( $self, $cmd ) = @_; local $ENV{'HOME'} = $self->homedir(); local $ENV{'PATH'} = join( ":", ac_info( "bindir"), $ENV{'PATH'} ); delete $ENV{'LANGUAGE'}; delete $ENV{'LANG'}; local $ENV{'LC_ALL'} = $self->{'_locale'}; chdir $self->{'_rundir'} or croak "chdir failed; $!\n"; open STDOUT, "> $self->{'_stdout_file'}" or croak "failed to redirect STDOUT: $!\n"; open STDERR, "> $self->{'_stderr_file'}" or croak "failed to redirect STDERR: $!\n"; exec( "/bin/sh", "-c", $cmd ) or croak "exec failed: $!\n"; } sub _make_cmd_result { my ( $self, $cmd, $pid ) = @_; waitpid $pid, 0 or croak "waitpid failed: $!\n"; my $result = new Lire::Test::CommandResult( '_command' => $cmd, '_status' => $?, ); $result->{'_stdout'} = file_content( $self->{'_stdout_file'} ); $result->{'_stderr'} = file_content( $self->{'_stderr_file'} ); $result->{'_sent_mail'} = $self->sent_mail(); return $result; } =pod =head2 sent_mail() Returns in an array reference the message that were sent out during the test. The element of this array are hash reference containing two keys: =over =item recipients An array reference containing the recipients as passed on the command line to sendmail. =item message The email which was sent. This is the complete text of the email. This is what was passed to sendmail via STDIN. =back =cut sub sent_mail { my $self = $_[0]; my $sent_mail = []; my $dir = new IO::Dir( $self->{'_maildir'} ); my @emails = map { /(.*)\.recipients/ } grep { $_ =~ /\.recipients$/ } $dir->read; $dir->close; foreach my $base ( @emails ) { my $mail = { 'recipients' => [], 'message' => undef, }; $mail->{'recipients'} = [split ' ', file_content( "$self->{'_maildir'}/$base.recipients" )]; $mail->{'message'} = file_content( "$self->{'_maildir'}/$base.message" ); push @$sent_mail, $mail; } return $sent_mail; } =pod =head2 create_test_file( $filename, [$content] ) Create a file $filename with the content $content. This file will be removed after the test is run during the tear_down() method. An empty file will be created if the $content parameter is omitted. =cut sub create_test_file { my ( $self, $filename, $content ) = @_; check_param( $filename, 'filename', sub { ! -f $_[0] }, 'file already exists' ); $content = "" unless defined $content; create_file( $filename, $content ); push @{$self->{'_test_files'}}, $filename; return; } =pod =head2 install_xml_spec( $spec_type, $superservice, $file ) Install the XML specification in $file of base schema $superservice. The $spec_type parameter specify where the file will be installed: =over =item site_filter The file will be installed as a filter specification in the system directory. =item site_report The file will be installed as a report specification in the system directory. =item site_schema The file will be installed as a schema specification in the system directory. =item filter The file will be installed as a filter specification in the HOME directory. =item report The file will be installed as a report specification in the HOME directory. =item schema The file will be installed as a schema specification in the HOME directory. =back These files will be removed after the test. =cut sub install_xml_spec { my ( $self, $spec_type, $superservice, $spec_file ) = @_; check_param( $spec_type, 'spec_type', qr/^(site_filter|site_schema|site_report|filter|report||schema)$/, "invalid spec_type parameter" ); check_param( $superservice, 'superservice' ); check_param( $spec_file, 'spec_file', sub { -f $_[0] && -r $_[0] }, "file doesn't exists" ); my $tree_root = $self->_find_tree_root( $spec_type ); my $spec_dir = $self->_find_spec_dir( $spec_type, $superservice ); unless (-d "$tree_root/$spec_dir" ) { mkdir "$tree_root/$spec_dir", 0775 or croak "can't create directory $tree_root/$spec_dir"; } my $filename = basename( $spec_file ); copy( $spec_file, "$tree_root/$spec_dir/$filename" ) or croak "copy failed: $!"; push @{$self->{'_test_files'}}, "$tree_root/$spec_dir/$filename"; return; } sub _find_tree_root { my ( $self, $spec_type) = @_; return $spec_type =~ /^site_/ ? ac_path( "datadir", "PACKAGE" ) : $self->{'_homedir'} . "/.lire"; } sub _find_spec_dir { my ( $self, $spec_type, $superservice ) = @_; if ( $spec_type =~ /filter/ ) { return "filters/$superservice"; } elsif ( $spec_type =~ /schema/ ) { return "schemas"; } else { return "reports/$superservice"; } } =pod =head2 create_test_cfg_file( $name ) Returns a Lire::Config::ConfigFile object initialized with the appropriate config specification. This configuration file will be created under $HOME/.lire/config/$name.xml when lire_run() will be used. It can be use to set config option which will be used when the command is run: my $cfg = $self->create_test_cfg_file( "test" ); $cfg->global->get( "lr_from" )->set( "flacoste\@logreport.org" ); If a configuration file $name was already created, it returns the associated ConfigFile object. Note that if you want these configurations variable to have effect when running test in-process ( not via lire_run() ), you have to call save() on the object before calling Lire::Config->init(). Otherwise, you better set the configuration option directly using the Lire::Config API. =cut sub create_test_cfg_file { my ($self, $name) = @_; check_param( $name, 'name', qr/^[a-zA-Z0-9_-]+$/, "'name' parameter should only contains digits, letters, '-' and '_'" ); return $self->{'_config_files'}{$name} if exists $self->{'_config_files'}{$name}; my $config_file = $self->homedir . "/.lire/config/$name.xml"; my $cfg = new Lire::Config::ConfigFile( 'filename' => $config_file, 'spec' => $self->{'_spec'} ); $cfg->global( $self->{'_spec'}->instance ); $self->{'_config_files'}{$name} = $cfg; return $cfg; } sub _create_cfg_files { my $self = $_[0]; foreach my $cfg_file ( values %{$self->{'_config_files'}}) { $cfg_file->save(); } } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Test::Unit::TestCase(3pm) =head1 VERSION $Id: FunctionalTestCase.pm,v 1.27 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Test/CursesUIDriver.pm0000644000175000017500000002431410460673257015751 00000000000000package Lire::Test::CursesUIDriver; use strict; use Carp; use Curses; use Curses::UI; use Lire::Utils qw/ check_param check_object_param /; # item_index also exists in Curses *lr_item_index = \&Lire::Utils::item_index; =pod =head1 NAME Lire::Test::CursesUIDriver - Object that can be used to drive a Curses::UI interface =head1 SYNOPSIS XXX =head1 DESCRIPTION XXX =cut sub new { my $class = shift; return bless { '_event_loop_handlers' => [], '_fatalerror_ref' => undef, '_do_one_event_ref' => undef }, $class; } sub setup_curses_ui { my $self = $_[0]; $Curses::UI::rootobject = undef; $Curses::UI::debug = 0; $Curses::UI::screen_too_small = 0; $Curses::UI::initialized = 0; $Curses::UI::color_support = 0; $Curses::UI::color_object = 0; $Curses::UI::ncurses_mouse = Curses->can('NCURSES_MOUSE_VERSION') && NCURSES_MOUSE_VERSION() >= 1; $self->{'_do_one_event_ref'} = \&Curses::UI::do_one_event; $self->{'_fatalerror_ref'} = \&Curses::UI::fatalerror; $self->{'_old_initscr'} = \&Curses::UI::initscr; { no warnings 'redefine'; *Curses::UI::initscr = sub {}; *Curses::UI::do_one_event = sub { $self->event_loop_dispatcher( @_ ) }; *Curses::UI::fatalerror = \&fatalerror; } $self->{'term'}->delscreen() if ( $self->{'term'} ); $self->{'term'} = newterm( undef, \*STDIN, \*STDOUT ); def_prog_mode(); return; } sub set_curses_ui { my ( $self, $ui ) = @_; check_object_param( $ui, 'ui', 'Curses::UI' ); croak "you need to call teardown_curses_ui() before calling set_curses_ui() again" if defined $self->{'_ui'}; $self->{'_ui'} = $ui; return; } sub teardown_curses_ui { my $self = $_[0]; endwin(); $self->{'_ui'} = undef; { no warnings 'redefine'; *Curses::UI::initscr = $self->{'_old_initscr'}; *Curses::UI::do_one_event = $self->{'_do_one_event_ref'}; *Curses::UI::fatalerror = $self->{'_fatalerror_ref'}; } return; } sub _find_menu { my ( $self, $menu_items, $menu_id ) = @_; foreach my $menu ( @{$menu_items} ) { return $menu if ( $menu->{'-label'} eq $menu_id ); } return undef; } sub event_loop_dispatcher { my ( $self, $ui, $widget ) = @_; croak "no event loop handlers available in current CursesUIDriver" unless @{ $self->{'_event_loop_handlers'} }; my $handler = shift @{ $self->{'_event_loop_handlers'} }; $handler->( $ui, $widget ); $widget->{'-has_modal_focus'} = 0 if ( exists $widget->{'-has_modal_focus'} ); return; } sub add_event_loop_handler { my ( $self, $handler ) = @_; check_param( $handler, 'handler' ); croak "'handler' should be a CODE ref, not '$handler'" unless ( ref $handler eq 'CODE' ); push @{ $self->{'_event_loop_handlers'} }, $handler; return; } sub fatalerror { croak @_; } sub find_menu_def { my ( $self, $menu_path ) = @_; croak "set_curses_ui() wasn't called" unless defined $self->{'_ui'}; check_param( $menu_path, 'menu_path' ); my ($mb_id, @path) = split '/', $menu_path; croak "'menu_path' should have at least 2 components" unless (@path); my $menubar = $self->{'_ui'}->getobj( $mb_id ); croak "no '$mb_id' menubar" unless defined $menubar; my $menu_items = $menubar->{'-menu'}; my $seen_menus = [ $mb_id ]; my $current_menu; foreach my $menu_id ( @path ) { $current_menu = $self->_find_menu( $menu_items, $menu_id ); unless ( defined $current_menu ) { croak (( @$seen_menus == 1 ) ? "no '$menu_id' menu in '$mb_id' menubar" : "no '$menu_id' submenu in '" . join ( '/', @$seen_menus ) . "' menu" ); } push @$seen_menus, $menu_id; $menu_items = $current_menu->{'-submenu'}; } return $current_menu; } sub activate_menu { my ( $self, $menu_path ) = @_; my $current_menu = $self->find_menu_def( $menu_path ); my ($mb_id, @path) = split '/', $menu_path; my $menubar = $self->{'_ui'}->getobj( $mb_id ); croak "no callback defined for '" . join ( '/', @path ) . "' in '$mb_id' menubar" unless ( defined $current_menu->{'-value'} && ( ref $current_menu->{'-value'} eq 'CODE' ) ); $current_menu->{'-value'}->( $menubar ); return; } sub top_window { my $self = $_[0]; my $focused = $self->{'_ui'}->focus_path(-1); if ( $focused->isa( 'Curses::UI::Menubar' ) ) { my $mbar = $focused; $focused->loose_focus(); $focused = $self->{'_ui'}->focus_path(-1); $mbar->focus(); } return ( $focused->isa( 'Curses::UI::Window' ) ? $focused : $focused->parentwindow() ); } sub _widget_path { my ( $self, $widget ) = @_; my @path; while ( $widget ne $self->{'_ui'} ) { my $parent = $widget->parent(); my $widget_id = $parent->{'-object2id'}{$widget}; die "widget not linked to its container?" unless defined $widget_id; push @path, $widget_id; $widget = $parent; } return '/' . join( '/', reverse @path ); } sub find_widget { my ( $self, $path ) = @_; check_param( $path, 'path' ); return $self->{'_ui'}->focus_path(-1) if ( $path eq '.' ); my @widgets = split '/', $path; my $widget; my $seen_path; if ( ! defined $widgets[0] || $widgets[0] eq '' ) { shift @widgets; $widget = $self->{'_ui'}; $seen_path = ''; } else { $widget = $self->top_window(); $seen_path = $self->_widget_path( $widget ); } foreach my $id ( @widgets ) { $widget = $widget->getobj( $id ); croak "no widget '$id' in " . ( $seen_path ? "'$seen_path'" : "root" ) . " container" unless defined $widget; $seen_path .= "/$id"; } return $widget; } sub click_button { my ( $self, $path, $button ) = @_; check_param( $path, 'path' ); check_param( $button, 'button' ); my $button_box = $self->find_widget( $path ); croak "'" . $self->_widget_path( $button_box ) . "' should be a Curses::UI::Buttonbox widget, not '$button_box'" unless $button_box->isa( 'Curses::UI::Buttonbox' ); my $buttons = $button_box->{'-buttons'}; my $button_idx; for ( my $idx = 0; $idx < @$buttons; $idx++ ) { if ( $buttons->[$idx]->{'-label'} eq $button ) { $button_idx = $idx; last; } } croak "no '$button' button in '" . $self->_widget_path( $button_box ) . "' Buttonbox" unless defined $button_idx; $button_box->{'-selected'} = $button_idx; my $callback = $buttons->[$button_idx]->{'-onpress'}; $callback->( $button_box ) if ( defined $callback && ref $callback eq 'CODE' ); return; } sub enter_text { my ( $self, $path, $text ) = @_; check_param( $path, 'path' ); check_param( $text, 'text' ); my $widget = $self->find_widget( $path ); $widget->parent()->focus( $widget, 1 ); foreach my $char ( split //, $text ) { $widget->event_keypress( $char ); } return; } sub enter_key { my ( $self, $path, $char ) = @_; check_param( $path, 'path' ); check_param( $char, 'char', qr/^([0-9]+|\w)$/, "'char' should be either an integer or a single character" ); my $widget = $self->find_widget( $path ); $widget->parent()->focus( $widget, 1 ); $widget->event_keypress( $char ); return; } sub select_items { my ( $self, $path, @items ) = @_; check_param( $path, 'path' ); croak "at least one 'item' parameter is required" unless @items; my $widget = $self->find_widget( $path ); my $abs_path = $self->_widget_path( $widget ); croak "'$abs_path' should be a Curses::UI::Listbox or Curses::UI::Popupmenu widget, not '$widget'" unless ( $widget->isa( 'Curses::UI::Listbox' ) || $widget->isa( 'Curses::UI::Popupmenu' ) ); croak "'$abs_path' doesn't support multi-selection" if ( @items > 1 && !$widget->{'-multi'} ); my $selection = []; my $labels = $self->_widget_displayed_labels( $widget ); foreach my $item ( @items ) { my $idx = lr_item_index( $labels, $item ); croak "'$abs_path' doesn't have any '$item' item" unless defined $idx; push @$selection, $idx; } if ( $widget->isa( 'Curses::UI::Listbox' ) ) { $widget->set_selection( @$selection ); } else { my $old_sel = $widget->{'-selected'}; $widget->{'-selected'} = $selection->[0]; $widget->run_event('-onchange') if ( ! defined $old_sel || $old_sel != $widget->{'-selected'} ); } return; } sub _widget_displayed_labels { my ( $self, $widget ) = @_; return $widget->{'-values'} unless defined $widget->{'-labels'}; my @labels = (); foreach my $val ( @{$widget->{'-values'}} ) { push @labels, ( defined $widget->{'-labels'}{$val} ? $widget->{'-labels'}{$val} : $val ); } return \@labels; } sub DESTROY { my $self = $_[0]; $self->{'term'}->delscreen() if ( $self->{'term'} ); } 1; =pod =head1 SEE ALSO Curses::UI(3pm) =head1 VERSION $Id: CursesUIDriver.pm,v 1.15 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Test/Mock.pm0000644000175000017500000002433010460673260013754 00000000000000package Lire::Test::Mock; use strict; use vars qw/%FACTORIES %FACTORY_RESULTS %MOCK_INSTANCES/; use Class::Inner; use Devel::Symdump; use Lire::Utils qw/check_param check_object_param/; use Carp; %FACTORIES = (); %MOCK_INSTANCES = (); %FACTORY_RESULTS = (); =pod =head1 NAME Lire::Test::Mock - Create mock object =head1 SYNOPSIS use Lire::Report; use Lire::Test::Mock; use Lire::DlfResult; my $mock = new Lire::Test::Mock( 'Lire::Report' ); $mock->set_result( 'timestamp', $time ); $mock->timestamp(); # will return $time $mock->get_calls(); # [ 'timestamp' ] $mock->get_invocation( 'timestamp', 0 ); # [ $mock ] =head1 DESCRIPTION This class makes it easy to defined mock objects. Mock objects are objects which offers the same interface than another object but which do not share its functionality. This makes it easier to test objects which requires fixtures which have lots of dependencies. The mock object can be used to collect information about calls made on the object. Returns value for such method invocation can also be specified. =head2 new( $class, 'method' => $result, 'method' => $result ) Creates a new mock object that will wrap $class. Any other keyword arguments will be use to initialize the result of methods call. See set_result() for information on how this works. =cut sub new { my ( $self, $class, %results ) = @_; my $methods = _create_methods( $class ); $methods->{'new'} = sub { return bless( {}, shift ) }; $self = new Class::Inner( 'parent' => $class, 'methods' => $methods ); _init_mock( $self, $class, 'new' ); $self->set_result( %results ) if %results; return $self; } =pod =head2 new_proxy( $class, @constructor_params ) This creates mock object which for the base $class. A proxy mock object will still monitor calls to the object but the real methods will be invoked, unless a result was specified using set_result(). Any remaining parameters will be passed to the new() method which should be defined in the class. =head2 new_proxy( $instance ) Makes a Lire::Test::Mock object which is a clone of $instance. =cut sub new_proxy { my $pkg = shift; my $class = shift; check_param( $class, 'class' ); return new_proxy_instance Lire::Test::Mock( $class ) if ref $class; my $args = [ @_ ]; my $methods = _create_methods( $class ); my $self = new Class::Inner( 'parent' => $class, 'args' => $args, 'methods' => $methods ); _init_mock( $self, $class ); $self->{'_proxy'} = 1; return $self; } sub new_proxy_instance { my ( $pkg, $proto ) = @_; check_object_param( $proto, 'proto', 'HASH' ); my $class = ref $proto; my $methods = _create_methods( $class ); $methods->{'new'} = sub { bless $proto, shift }; my $self = new Class::Inner( 'parent' => $class, 'methods' => $methods ); _init_mock( $self, $class ); $self->{'_proxy'} = 1; return $self; } =pod =head2 is_proxy() Returns whether this mock object will proxy to the real methods when no results was defined for a specific method. =cut sub is_proxy { return $_[0]{'_proxy'}; } sub _init_mock { my ( $mock, $class ) = @_; $mock->{'_base'} = $class; $mock->{'_results'} = {}; $mock->{'_calls'} = []; $mock->{'_invocations'} = {}; $mock->{'_proxy'} = 0; foreach my $name ( list_methods( $class ) ) { next if $name eq 'new'; $mock->{'_invocations'}{$name} = []; } return; } sub _create_methods { my $class = $_[0]; my %methods = (); foreach my $name ( list_methods( $class ) ) { next if $name eq 'new'; next if $name eq 'DESTROY'; $methods{$name} = gen_mock_method( $name ); } $methods{'get_calls'} = \&get_calls; $methods{'set_result'} = \&set_result; $methods{'get_invocation'} = \&get_invocation; $methods{'invocation_count'} = \&invocation_count; $methods{'is_proxy'} = \&is_proxy; return \%methods; } sub gen_mock_method { my $name = $_[0]; return sub { my $self = $_[0]; push @{$self->{'_calls'}}, $name; push @{$self->{'_invocations'}{$name}}, [ @_ ]; if ( $self->{'_proxy'} && ! defined $self->{'_results'}{$name} ) { my $method = UNIVERSAL::can( $self->{'_base'}, $name ); return $method->( @_ ); } return unless exists $self->{'_results'}{$name}; my $value = $self->{'_results'}{$name}; return $value->( @_ ) if ref $value && ref $value eq 'CODE'; return $value; }; } sub list_methods { my $class = $_[0]; check_param( $class, 'class' ); my @methods = map { $_=~ s/^$class\:://; $_ } Devel::Symdump->functions( $class ); no strict 'refs'; foreach my $base ( @{"$class\::ISA"} ) { push @methods, list_methods( $base ); } my %methods = map { $_ => 1 } @methods; return keys %methods } =pod =head2 get_calls() Returns an array reference containing all the methods called on the object. =cut sub get_calls { return [ @{$_[0]{'_calls'}} ]; } =pod =head2 invocation_count( $method ) Returns the number of time $method was called. =cut sub invocation_count { my ( $self, $method ) = @_; check_param( $method, 'method' ); croak "no method '$method' defined in $self->{'_base'}" unless exists $self->{'_invocations'}{$method}; return scalar @{$self->{'_invocations'}{$method}}; } =pod =head2 get_invocation( $method, $index ) Returns the parameter that were given when method $method was called. =cut sub get_invocation { my ( $self, $method, $index ) = @_; check_param( $method, 'method' ); $index ||= 0; croak "no method '$method' defined in $self->{'_base'}" unless exists $self->{'_invocations'}{$method}; croak "no invocation $index for method '$method'" unless $index < @{$self->{'_invocations'}{$method}}; return $self->{'_invocations'}{$method}[$index]; } =pod =head2 set_result( method => $result, ... ) This assign the result $result to $method. If $result is a code reference, it will be invoked with the same argument than the method to compute the result. =cut sub set_result { my ( $self, %results ) = @_; foreach my $method ( keys %results ) { croak "no method '$method' defined in $self->{'_base'}" unless exists $self->{'_invocations'}{$method}; $self->{'_results'}{$method} = $results{$method}; } return; } =pod =head1 USING MOCK FACTORIES Sometime, it is not possible to instatiate a proxy or mock object during fixture setup. This will usually happen when the object which we want to track access to is instantiated by the method under test. In these cases, one can use the set_mock_factory() class method to change the factory method to one that will return a proxy instance instead of a real instance. One should call reset_factories() during tear_down() so that the real factory method become directly accessible once again. =head2 set_mock_factory( $class, %results ) Make the new() method of package $class returns proxy Lire::Test::Mock instance. The created instances will be accessible through the mock_instances() method. Any other argument will be passed to the set_result() method when the mock instance is created. =cut sub set_mock_factory { my ( $pkg, $class, %results ) = @_; check_param( $class, 'class' ); return if exists $FACTORIES{$class}; my $factory = $class->can( 'new' ); croak "no new() method in class $class" unless $factory; no strict 'refs'; $FACTORIES{$class} = *{"${class}\::new"}{'CODE'}; $FACTORY_RESULTS{$class} = \%results; $MOCK_INSTANCES{$class} = []; no warnings 'redefine'; *{"${class}\::new"} = sub { my $self = $factory->( @_ ); my $mock = new_proxy_instance Lire::Test::Mock( $self ); $mock->set_result( %{$FACTORY_RESULTS{$class}} ); push @{$mock->{'_calls'}}, 'new'; push @{$mock->{'_invocations'}{'new'}}, [ @_ ]; push @{$MOCK_INSTANCES{$class}}, $mock; return $mock; }; return; } =pod =head2 mock_instances( $class ) Returns an array reference containing all the instance that were created by the installed mock factory in $class. This method will throw an exception if now mock factory was installed for class $class. =cut sub mock_instances { my ( $pkg, $class ) = @_; check_param( $class, 'class' ); croak "no mock factory installed for class '$class'" unless exists $MOCK_INSTANCES{$class}; return $MOCK_INSTANCES{$class}; } =pod =head2 reset_factories() Removes all mock factories that were set up using set_mock_factory(). =cut sub reset_factories { my $pkg = $_[0]; while ( my ( $class, $factory ) = each %FACTORIES ) { no strict 'refs'; no warnings 'redefine'; if ( $factory ) { *{"$class\::new"} = $factory; } else { delete "$class\::"->{'new'}; } } %FACTORIES = (); %MOCK_INSTANCES = (); %FACTORY_RESULTS = (); return; } 1; __END__ =pod =head1 SEE ALSO Test::Unit::TestCase(3pm) =head1 VERSION $Id: Mock.pm,v 1.5 2006/07/23 13:16:32 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Group.pm0000644000175000017500000004274010460673255013251 00000000000000package Lire::Group; use strict; use base qw/ Lire::Aggregator /; use Carp; use Lire::DlfQuery; use Lire::ReportOperator qw/ group_data_value /; use Lire::DataTypes qw/ check_int is_numeric_type /; =pod =head1 NAME Lire::Group - Base class for implementation of the group aggregator =head1 SYNOPSIS use Lire::Group; =head1 DESCRIPTION This module is the base class for implementation of the group aggregator. This aggregator will split the DLF records in groups having the same key. The key is made up of one or more several non-numerical fields. The number of keys to keep in the report can be configured through the limit attribute. The keys can also be sorted using the sort attribute. =head1 CONSTRUCTOR =head2 new( %params ) Creates a new instance of a group aggregator. In addition to the normal report operator parameters, the limit attribute can be initialized at creation time. =cut sub new { my $proto = shift; my $class = ref $proto || $proto; my $self = bless { 'fields' => [] }, $class; my %args = @_; $self->SUPER::init( @_, 'op' => 'group' ); $self->limit( $args{'limit'} ) if exists $args{'limit'}; return $self; } =pod =head1 METHODS =head2 limit( [$new_limit] ) Returns the number of keys to display in the report. This can be an integer or the name of one of the report specification parameter (when it starts by $). The limit attribute can be changed by passing a $new_limit parameter. =cut sub limit { my ( $self, $limit ) = @_; if ( @_ == 2 ) { if ( defined $limit && $limit =~ /^\$/ ) { my $name = substr $limit, 1; croak "$limit isn't a defined parameter" unless $self->report_spec->has_param( $name ); my $type = $self->report_spec->param( $name )->type(); croak "$limit parameter isn't of type int" unless $type eq "int"; $self->{'limit'} = $limit; } elsif ( defined $limit ) { croak "limit must be a positive integer" unless check_int( $limit ); $self->{'limit'} = $limit; } else { delete $self->{'limit'}; } } return $self->{'limit'}; } sub _max_entries { my $self = $_[0]; my $ratio; my $limit = $self->report_spec->resolve_param_ref( $self->{'limit'} ); return 0 unless ( $limit ); if ( $limit < 10 ) { $ratio = 2; } elsif ( $limit < 25 ) { $ratio = 1.5 } elsif ( $limit < 50 ) { $ratio = 1.25 } elsif ( $limit < 1000 ) { $ratio = 1.1 } else { $ratio = 1.05; } return int( $limit * $ratio ); } =pod =head2 sort_fields( [$new_sort_fields] ) Returns fields and/or operator values which are going to be used to sort the entries generated by this aggregator. This is an array reference containing group field names and/or operator's name. The sorting fields can be changed by passing a new array reference. =cut sub sort_fields { my ( $self, $fields ) = @_; if (@_ == 2 && defined $fields ) { croak "$fields isn't an array reference" unless UNIVERSAL::isa( $fields, "ARRAY" ); foreach my $f ( @$fields ) { croak "$f isn't a defined sort field name" unless $self->is_valid_sort_field( $f ); } if ( @$fields ) { $self->{'sort_fields'} = $fields; } else { delete $self->{'sort_fields'}; } } elsif ( @_ == 2 ) { delete $self->{'sort_fields'}; } return $self->{'sort_fields'}; } =pod =head2 group_fields( [$new_fields] ) Returns as a reference to an array of Lire::GroupField objects the DLF fields that are used to group the records. If the $new_fields is set, the DLF fields used to group the records will be changed. This parameter should be a reference to an array of Lire::GroupField objects. =cut sub group_fields { my ( $self, $fields ) = @_; if ( @_ == 2 ) { croak "$fields isn't an array reference" unless UNIVERSAL::isa( $fields, "ARRAY" ); croak "group fields array is empty" unless @$fields; foreach my $f ( @$fields ) { croak "$f isn't of type Lire::GroupField" unless UNIVERSAL::isa( $f, "Lire::GroupField" ); } $self->{'fields'} = $fields; } return $self->{'fields'}; } # Overrides Lire::Aggregator::build_query sub build_query { my ( $self, $query ) = @_; $self->SUPER::build_query( $query ); foreach my $field ( @{$self->{'fields'}} ) { $query->add_group_field( $field->name ); } $query->set_sort_spec( join( " ", @{$self->sort_fields()} ) ) if $self->sort_fields(); return; } # Overrides Lire::Aggregator::set_group_summary sub set_group_summary { my ( $self, $group, $row ) = @_; $self->SUPER::set_group_summary( $group, $row ); $group->show( $self->report_spec->resolve_param_ref( $self->{'limit'} ) ) if defined $self->{'limit'}; return; } # Implements Lire::Aggregator::create_entry sub create_entry { my ( $self, $group, $row ) = @_; my $max_entries = $self->_max_entries(); return undef if $max_entries && $group->entries() >= $max_entries; my @names = (); foreach my $field ( @{$self->{'fields'}} ) { my $value = $row->{ $field->name() }; unless ( defined $value ) { $group->missing_cases( $group->missing_cases() + $row->{'_lr_nrecords'} ); return undef; } push @names, $row->{ $field->name() }; } if ( @names ) { my $entry = $group->create_entry(); foreach my $n ( @names ) { $entry->add_name( $n ); } return $entry; } # Not reached } # ------------------------------------------------------------------------ # Method is_name_defined() # # Overide Lire:::Aggregator one to also check among the group fields sub is_name_defined { my ( $self, $name ) = @_; # Check in fields foreach my $f ( @{$self->{'fields'}} ) { return 1 if $f->name eq $name; } # Chain up $self->SUPER::is_name_defined( $name ); } #------------------------------------------------------------------------ # Method is_valid_sort_field( $name ) # # Method that checks if the name is valid as a sorting field. It is # only if the name is the name of one of the operator in this group. # It can optionnally be prefixed by - to specify descending sort # order. sub is_valid_sort_field { my ( $self, $name ) = @_; # Remove descending control char $name =~ s/^-//g; $self->is_name_defined( $name ); } # ------------------------------------------------------------------------ # Method xml_attrs() # # Implementation required by Lire::Aggregator sub xml_attrs { my ( $self ) = @_; my $attr = ""; if ( defined $self->{'sort_fields'} && @{$self->{'sort_fields'}}) { my $fields = join " ", @{$self->{'sort_fields'}}; $attr .= qq{ sort="$fields"}; } $attr .= qq{ limit="$self->{'limit'}"} if exists $self->{'limit'}; $attr; } # ------------------------------------------------------------------------ # Method print_content( $fh, $pfx ) # # Override to output the field elements. sub print_content { my ( $self, $fh, $pfx ) = @_; foreach my $f ( @{$self->{'fields'}} ) { $f->print( $fh, $pfx + 1); } $self->SUPER::print_content( $fh, $pfx ); } # Implements Lire::ReportOperator::name() sub name { return 'group:' . join( ".", map { $_->name() } @{$_[0]->group_fields()} ); } # Implements Lire::Aggregator::create_categorical_info sub create_categorical_info { my ( $self, $info ) = @_; foreach my $field ( @{$self->group_fields} ) { $field->create_categorical_info( $info ); } } # Implements Lire::ReportOperator::init_merge() sub init_merge { my $self = $_[0]; $self->SUPER::init_merge(); # We can't use the array data structure for merging # because we aren't seeing the entries sorted. $self->{'use_array'} = 0; if ( defined $self->limit() ) { $self->{'limit_view'} = $self->report_spec()->resolve_param_ref( $self->limit() ); # For better report merging, we add some entries. $self->{'limit_num'} = $self->_max_entries(); } $self->{'sort_cmp'} = $self->make_sort_function(); return; } #------------------------------------------------------------------------ # Method make_sort_function() # # Create a sort function which is used to sort the data according # to the sort specification. sub make_sort_function { my ( $self ) = @_; return unless $self->sort_fields; # Build sort function my ( $a_dflt, $b_dflt, $schwartzian ); if ( $self->{'use_array'}) { $a_dflt = '$_[0]'; $b_dflt = '$_[1]'; $schwartzian = ''; # Not using schwarzian transform } else { $a_dflt = '$a'; $b_dflt = '$b'; $schwartzian = '[1]'; # Using schwartzian transform } my @sort_ops = (); foreach my $f ( @{$self->sort_fields} ) { my ($a, $b) = ($a_dflt, $b_dflt ); if ( $f =~ /^-/ ) { $f = substr $f, 1; ($a,$b) = ($b,$a); } my $index; # This will contains the index of the field in the array my $summary = ""; # This will be used to get at the summary data my $cmp = '<=>'; # Default to numeric comparison my $i = 0; foreach my $group_field ( @{$self->group_fields} ) { if ( $group_field->name eq $f ) { $index = $i; if ( is_numeric_type( $group_field->field->type ) ) { $cmp = "<=>"; } else { $cmp = "cmp"; } last; } $i++; } # The sort field wasn't found in the group_fields, # look into the operators unless (defined $index) { $i = @{$self->group_fields}; foreach my $op ( @{$self->ops} ) { # Skip aggregators next if $op->isa( 'Lire::Aggregator' ); if ( $op->name eq $f ) { $index = $i; last; } $i++; } } # Its wasn't found in one of our ReportOperator children, use # the summary value of one of our aggregator children unless (defined $index ) { $i = @{$self->group_fields}; foreach my $op ( @{$self->ops} ) { # Only check aggregators next unless $op->isa( 'Lire::Aggregator' ); if ( $op->is_name_defined($f) ) { $index = $i; $summary = $self->get_summary_value_string( $f ); last; } $i++; } } croak "impossible to find $f value to sort on" unless defined $index; if ( $summary ) { push @sort_ops, 'group_data_value(' . $a ."->" . $schwartzian . "[$index]$summary ) $cmp group_data_value( " . $b ."->" . $schwartzian . "[$index]$summary)"; } else { push @sort_ops, $a ."->" . $schwartzian ."[$index] $cmp " . $b ."->" . $schwartzian . "[$index]"; } } my $sort_code = "sub { " . join( " || ", @sort_ops ) . " }"; my $sort_func = eval $sort_code; croak "error compiling sort comparison ($sort_code): $@" if $@; $sort_func; } # Implements Lire::Aggregator::init_aggregator_data() sub init_aggregator_data { my ( $self ) = @_; # The group datastructure used to hold the operations' data of the # group element is an array. It contains the fields value and the # op data: # [ group field, group field, ..., op data, op data, op data ] if ( $self->{'use_array'}) { # To minimize memory, we operate on sorted input by keeping # the key in final sorted order and keeping only the minimum # needed # # Structure of the array: we keep in the first element the current # group key, the second element is the current group element data. # After this we have the processed group elements data in sort order # and up the the limit attribute. # [ current_key, current_group_data, sorted_group_data, sorted_group_data, ... ] return []; } else { # For merging we don't see sorted input and keep related keys # using a hash. return {} } } sub item_data2sort_key { my $key = []; foreach my $f ( @{$_[0]} ) { push @$key, group_data_value( $f ); } return $key; } # Implements Lire::Aggregator::merge_aggregator_data() sub merge_aggregator_data { my ( $self, $group, $data ) = @_; foreach my $e ( $group->entries ) { my $key = join( ";", map { $_->{'value'} } $e->names ); my $key_data = $data->{$key}; unless ( $key_data ) { $key_data = $data->{$key} = []; my $i = 0; my @names = $e->names; croak "wrong number of names: expected ", scalar @{$self->group_fields}, " but found ", scalar @names if @names != @{$self->group_fields}; foreach my $f ( @{$self->group_fields} ) { $key_data->[$i] = $names[$i]{'value'}; $i++; } foreach my $op ( @{$self->ops} ) { $key_data->[$i++] = $op->init_group_data(); } } my $i = @{$self->group_fields}; foreach my $op ( @{$self->ops} ) { my $value = $e->data_by_name( $op->name ); my $op_data = $key_data->[$i++]; $op->merge_group_data( $value, $op_data ) if ( $value ); } } } =pod =head2 binary_insert Recursive function that uses a binary search to insert $item in $array using $cmp as comparison operator. $first_idx and $max_idx specify the boundaries of the search. Search ends when $first_idx == $max_idx or when $sort_key sorts at or before $first_idx or at or after $max_idx =cut sub binary_insert { my ( $item, $sort_key, $array, $cmp, $first_idx, $max_idx ) = @_; my $mid_idx = int( ($max_idx - $first_idx) / 2) + $first_idx; my $sort = $cmp->( $sort_key, item_data2sort_key( $array->[$mid_idx] ) ); if ( ($first_idx == $mid_idx && $sort <= 0) || ($max_idx == $mid_idx && $sort >= 0 ) || $sort == 0 ) { # Search has ended, insert according to sort order if ( $sort < 0 ) { # Sort before mid_idx splice( @$array, $mid_idx, 0, $item); } else { # Sort right after mid_idx splice( @$array, $mid_idx + 1, 0, $item); } } else { # Recurse if ( $sort < 0 ) { binary_insert( $item, $sort_key, $array, $cmp, $first_idx, $mid_idx - 1 ); } else { binary_insert( $item, $sort_key, $array, $cmp, $mid_idx + 1, $max_idx ); } } } sub sort_current_group_element { my ( $self, $data ) = @_; # Case where @$data is empty return unless @$data; my $item = $data->[1]; # This data item is ended my $i = @{$self->group_fields}; foreach my $op ( @{$self->ops} ) { $op->end_group_data( $item->[$i++] ); } if ( $self->{'sort_cmp'}) { my $key = item_data2sort_key( $item ); my $cmp = $self->{'sort_cmp'}; if ( @$data == 2 ) { push @$data, $item; # Small optimization: check for before or at end of array condition } elsif ( $cmp->( $key, item_data2sort_key( $data->[2] ) ) <= 0 ) { splice @$data, 2, 0, $item; } elsif ( $cmp->( $key, item_data2sort_key( $data->[$#$data])) >= 0 ) { push @$data, $item; } else { binary_insert( $item, $key, $data, $cmp, 2, $#$data ); } } else { # Push at end push @$data, $item; } # Keep only limit records if ( $self->{'limit_num'} ) { my $max_count = $self->{'limit_num'} + 2; # last_key, current_element splice @$data, $max_count if $max_count < @$data ; } } # Implements Lire::Aggregator::end_aggregator_data() sub end_aggregator_data { my ( $self, $data ) = @_; if ( $self->{'use_array'} ) { $self->sort_current_group_element( $data ); # Remove last_key, current_element splice @$data,0,2; } else { foreach my $key ( keys %$data ) { my $item = $data->{$key}; my $i = @{$self->group_fields}; foreach my $op ( @{$self->ops} ) { $op->end_group_data( $item->[$i++] ); } } # Sort the keys according to the sort value my @sorted_keys; if ( $self->sort_fields ) { my $cmp = $self->{'sort_cmp'}; # This uses schwartzian transform @sorted_keys = map { $_->[0] } sort $cmp map { [ $_, item_data2sort_key( $data->{$_} ) ] } keys %$data; } else { @sorted_keys = keys %$data; } # Keep only limit records if ( $self->{'limit_num'} ) { my $limit = $self->{'limit_num'}; splice @sorted_keys, $limit if ($limit < @sorted_keys ); } # Delete unused keys %$data = map { $_ => $data->{$_} } @sorted_keys; $data->{'_lr_sorted_keys'} = \@sorted_keys; } $data; } # Implements Lire::Aggregator::create_group_entries() sub create_group_entries { my ( $self, $group, $data ) = @_; $group->show( $self->{'limit_view'} ) if $self->{'limit_view'}; # Either to the sorted group data # or the sorted keys my $array_ref; if ( $self->{'use_array'} ) { $array_ref = $data; } else { $array_ref = $data->{'_lr_sorted_keys'}; } my $field_count = @{$self->group_fields}; foreach my $elmnt ( @$array_ref ) { my $item; if ( $self->{'use_array'} ) { $item = $elmnt; } else { $item = $data->{$elmnt}; } my $entry = $group->create_entry; my $i = 0; while ( $i < $field_count ) { $entry->add_name( $item->[$i++] ); } foreach my $op ( @{$self->ops} ) { $op->add_entry_value( $entry, $item->[$i++] ); } } } 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::GroupField(3pm), Lire::ReportOperator(3pm) =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 VERSION $Id: Group.pm,v 1.36 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/0000755000175000017500000000000011677607767013115 500000000000000lire-2.1.1/all/lib/Lire/Config/StringSpec.pm0000644000175000017500000000446510460673256015446 00000000000000package Lire::Config::StringSpec; =pod =head1 NAME Lire::Config::StringSpec - String parameter. =head1 DESCRIPTION Lire::Config::TypeSpec that represents any string of characters Values of this type can be any string. The specification can have a 'valid-re' attribute which will make sure that the value matches the given regular expression. =cut use base qw/Lire::Config::ScalarSpec/; =pod =head2 new( 'name' => $name, [ 'valid-re' => $valid_re ], ... ); Creates a new StringSpec. The 'valid-re' parameter can be used to initialize the valid_re attribute. =cut sub new { my $self = shift->SUPER::new( @_ ); my %args = @_; $self->valid_re( $args{'valid-re'} ) if exists $args{'valid-re'}; return $self; } =pod =head2 valid_re( [ $new_valid_re ] ) Returns (and optionally change) the validation regular expression that values from this spec should match. =cut sub valid_re { my $self = $_[0]; if ( @_ == 2 ) { $self->{'_valid_re'} = $_[1]; $self->{'_compiled_re'} = defined $_[1] ? qr/$_[1]/ : undef; } return $self->{'_valid_re'}; } sub is_valid { my ( $self, $value ) = @_; return !$self->required() unless defined $value; return 1 unless defined $self->{'_compiled_re'}; return scalar $value =~ /$self->{'_compiled_re'}/; } sub normalize { return $_[1]; } 1; __END__ =pod =head1 VERSION $Id: StringSpec.pm,v 1.4 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/BasePluginSpec.pm0000644000175000017500000000513010460673256016217 00000000000000package Lire::Config::BasePluginSpec; use strict; =pod =head1 NAME Lire::Config::BasePluginSpec - PluginManager based PluginSpec =head1 DESCRIPTION This is Lire::Config::PluginSpec that determines its valid list of options from the Lire::PluginManager. =cut use base qw/Lire::Config::PluginSpec/; use Lire::Config::OptionSpec; use Lire::PluginManager; use Carp; =pod =head2 new() Create a Lire::Config::BasePluginSpec object. =head2 plugin_type() Subclasses should defines a plugin_type() method that would be use to select the available options. =cut sub plugin_type { croak ref shift, '::plugin_type() unimplemented'; } sub is_valid { my ( $self, $val ) = @_; return !$self->required() unless defined $val; return Lire::PluginManager->has_plugin( $self->plugin_type(), $val ); } sub normalize { my ( $self, $val ) = @_; return $self->is_valid( $val ) ? $val : undef; } sub add { croak( ref shift, ' cannot contain any components' ); } sub options { my $self = $_[0]; my @options; my $mgr = Lire::PluginManager->instance(); foreach my $name ( @{$mgr->plugin_names( $self->plugin_type() ) } ) { my $plugin = $mgr->get_plugin( $self->plugin_type(), $name ); push @options, new Lire::Config::OptionSpec( 'name' => $name, 'summary' => $plugin->title(), 'description' => $plugin->description() ); } return sort { $a->name() cmp $b->name() } @options; } 1; __END__ =pod =head1 SEE ALSO Lire::Config::DlfConverterSpec(3pm) Lire::Config:: =head1 VERSION $Id: BasePluginSpec.pm,v 1.3 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/Scalar.pm0000644000175000017500000000674610765035043014570 00000000000000package Lire::Config::Scalar; use strict; use base qw/Lire::Config::Value/; use Locale::TextDomain 'lire'; use Lire::Utils qw/ xml_encode shell_quote/; use Carp; =pod =head1 NAME Lire::Config::Scalar - Lire Config container for scalar values =head1 SYNOPSIS use Lire::Config::Scalar =head1 DESCRIPTION This package contains the class to represent a scalar in an actual configuration. =head1 Lire::Config::Scalar Value container for scalar values. Implements simple methods to get() and set() string data. =cut sub new { my $self = shift->SUPER::new(@_); my %args = @_; $self->{'value'} = '' unless exists $self->{'value'}; $self->{'warned'} = 0; $self->set( $args{'value'} ) if exists $args{'value'}; return $self; } sub as_value { my $self = $_[0]; my $spec = $self->spec(); my $val = $spec->normalize( $self->{'value'} ); return $val if $spec->is_valid( $val ); unless ( $self->{'warned'} ) { carp __x( "invalid value for parameter '{parameter}': {value}", 'parameter' => $self->name(), 'value' => ( defined $val ? $val : '(undef)' ) ); $self->{'warned'} = 1; } return wantarray ? () : undef; } sub as_label { my $label = $_[0]->get(); return '' unless defined $label; $label =~ s/(^\s*|\s*$)//g; return $label; } sub as_shell_var { my $self = $_[0]; return ( $self->spec->is_valid( $self->{'value'} ) ? $self->name . "=" . shell_quote( $self->as_value() ) : '' ); } =pod =head2 get() Returns this scalar's value. =cut sub get { return $_[0]{'value'}; } =pod =head2 set( $val ) This method can be used to change this scalar's value. =cut sub set { my ($self, $val) = @_; $self->{'warned'} = 0; $self->{'value'} = $val; } =pod =head2 is_valid() Checks with the parameter's spec that the current value is valid. =cut sub is_valid { return $_[0]->{'spec'}->is_valid( $_[0]->{'value'} ); } sub is_equals { my ( $self, $param ) = @_; return 0 unless $self->SUPER::is_equals( $param ); no warnings 'uninitialized'; return $self->{'spec'}->normalize( $self->{'value'} ) eq $self->{'spec'}->normalize( $param->{'value'} ); } sub save_xml { my ( $self, $fh, $indent, $xmlns ) = @_; $indent ||= 0; $xmlns ||= ''; return if $self->is_default() || $self->spec()->obsolete(); if(defined $self->{'value'}) { print $fh ' 'x$indent, "<${xmlns}param name=\"", $self->name, "\">"; print $fh xml_encode($self->{'value'}), "\n"; } } 1; # whine, whine __END__ =head1 AUTHOR Wessel Dankers =head1 VERSION $Id: Scalar.pm,v 1.16 2008/03/09 19:27:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ExecutableSpec.pm0000644000175000017500000000350110460673256016247 00000000000000package Lire::Config::ExecutableSpec; use strict; =pod =head1 Lire::Config::ExecutableSpec Type that represents an executable. Executable values are only valid when the path they point to exists. =cut use base qw/Lire::Config::ScalarSpec/; use Lire::Utils qw/tilde_expand/; use File::Spec; sub is_valid { my ( $self, $val ) = @_; return !$self->required() unless defined $val; my $file = $self->normalize( $val ); return -x $file && -f _; } sub normalize { my ( $self, $val ) = @_; return undef unless defined $val; my $exe = tilde_expand( $val ); unless ( index($val, "/") != -1 ) { foreach my $d ( File::Spec->path ) { if (-f "$d/$exe" && -x "$d/$exe" ) { $exe = "$d/$exe"; last; } } } return File::Spec->canonpath( $exe ); } 1; __END__ =pod =head1 VERSION $Id: ExecutableSpec.pm,v 1.3 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/DlfStreamsSpec.pm0000644000175000017500000000374010460673256016237 00000000000000package Lire::Config::DlfStreamsSpec; use strict; use base qw/Lire::Config::ListSpec/; use Lire::DlfSchema; use Lire::Config::DlfStreamSpec; use Lire::Utils qw/check_param/; =pod =head1 NAME Lire::Config::DlfStreamsSpec - Holds DlfStream configuration. =head1 DESCRIPTION This Lire::Config::TypeSpec is a ListSpec which defines virtually one Lire::Config::DlfStreamSpec for each available schemas. This ListSpec subclass overrides the has_component() and get() methods to make a Lire::Config::DlfStreamSpec available for each defined schemas. =cut sub has_component { my ( $self, $name ) = @_; return ( $self->SUPER::has_component( $name ) || Lire::DlfSchema->has_schema( $name ) ); } sub get { my ( $self, $name ) = @_; check_param( $name, 'name' ); $self->add( new Lire::Config::DlfStreamSpec( 'name' => $name ) ) if ( $self->has_component( $name ) && ! $self->SUPER::has_component( $name ) ); return $self->SUPER::get( $name ); } 1; __END__ =pod =head2 SEE ALSO Lire::Config::DlfStreamsSpec(3pm), Lire::Config::DlfAnalyserSpec(3pm) =head1 VERSION $Id: DlfStreamsSpec.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/Reference.pm0000644000175000017500000000313510460673256015254 00000000000000package Lire::Config::Reference; use strict; use base qw/Lire::Config::Scalar/; use Carp; =pod =head1 NAME Lire::Config::Reference - Scalar which points to an Index. =head1 SYNOPSIS use Lire::Config::Reference; =head1 DESCRIPTION This is a scalar coming from a Lire::Config::ReferenceSpec and that will return the referenced entry in the Index when as_value() is called. =cut sub new { my $self = shift->SUPER::new(@_); croak "'spec' parameter should be a Lire::Config::ReferenceSpec instance" unless $self->{'spec'}->isa( "Lire::Config::ReferenceSpec" ); return $self; } sub as_value { my $self = $_[0]; return $self->{'spec'}->as_value( $self->get() ); } 1; # whine, whine __END__ =pod =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: Reference.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ReportConfigIndex.pm0000644000175000017500000000550510460673256016752 00000000000000package Lire::Config::ReportConfigIndex; use strict; use base qw/Lire::Config::Index/; use Lire::Utils qw/check_param check_object_param/; use Carp; =pod =head1 NAME Lire::Config::ReportConfigIndex - Index for store report configurations. =head1 SYNOPSIS =head1 DESCRIPTION This object make it possible to select from a list of ReportSpec. Each time as Lire::DlfStore is opened all the report configurations defined in it will be available under the 'store_report_specs' Index name. =head2 new( $list ) Creates a new ReportConfigIndex which wraps the $list report configurations list. This should be a Lire::Config::List instance with a spec that contains only one Lire::Config::ReportSpec component. =cut sub new { my ( $class, $list ) = @_; check_object_param( $list, 'list', 'Lire::Config::List' ); my @names = $list->spec()->component_names(); croak "'list' spec should contain only one Lire::Config::ReportSpec component" unless @names == 1 && $list->spec()->get( $names[0] )->isa( 'Lire::Config::ReportSpec' ); return bless { '_list' => $list }, $class; } sub has_entry { my ( $self, $name ) = @_; check_param( $name, 'name' ); foreach my $cfg ( $self->{'_list'}->elements() ) { no warnings 'uninitialized'; return 1 if $cfg->get( 'id' )->get() eq $name; } return 0; } sub entries { my $self = $_[0]; return [ sort map { $_->get( 'id' )->get() } $self->{'_list'}->elements() ]; } sub get_ref { my ( $self, $name ) = @_; check_param( $name, 'name' ); croak "no report configuration \"$name\"" unless $self->has_entry( $name ); foreach my $cfg ( $self->{'_list'}->elements() ) { no warnings 'uninitialized'; return $cfg->as_value() if $cfg->get( 'id' )->get() eq $name; } return; } 1; __END__ =pod =head1 SEE ALSO Lire::Config::ReportConfig(3pm) Lire:Config::Index(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: ReportConfigIndex.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/SelectSpec.pm0000644000175000017500000000410710460673256015410 00000000000000package Lire::Config::SelectSpec; use strict; =pod =head1 Lire::Config::SelectSpec Type that represents a choice. Values of this type can have one from a set of possible choices. The these values are normalized to the case specified in the options' specification. =cut use base qw/Lire::Config::CompoundSpec/; use Lire::Config::Scalar; use Lire::Utils qw/ check_param check_object_param /; sub instance_class { return 'Lire::Config::Scalar'; } =pod =head2 options() Returns as an array the valid options for this select. =cut sub options { return $_[0]->components(); } sub add { my ( $self, $option ) = @_; check_object_param( $option, 'option', 'Lire::Config::OptionSpec' ); $self->SUPER::add( $option ); return; } sub is_valid { my ( $self, $value ) = @_; return !$self->required() unless defined $value; return defined $self->normalize( $value ); } sub normalize { my ( $self, $value ) = @_; return undef unless defined $value; foreach my $o ( $self->options() ) { return $o->name() if $o->is_option( $value ); } return undef; } 1; __END__ =pod =head1 VERSION $Id: SelectSpec.pm,v 1.6 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/CommandSpec.pm0000644000175000017500000000336710460673256015556 00000000000000package Lire::Config::CommandSpec; use strict; =pod =head1 Lire::Config::CommandSpec Type that represents a UNIX command or program. A path lookup is done to canonicalize it, if appropriate. =cut use base qw/Lire::Config::ScalarSpec/; use File::Spec; sub is_valid { my ( $self, $val ) = @_; return !$self->required() unless defined $val; my $file = $self->normalize( $val ); return ( defined $file && -x $file ); } sub normalize { my ( $self, $val ) = @_; return undef unless defined $val; return File::Spec->canonpath($val) if index($val, '/') >= 0; foreach (split(':', $ENV{'PATH'})) { $_ = '.' if $_ eq ''; my $p = File::Spec->canonpath("$_/$val"); return $p if -x $p && -f _; } return undef; } 1; __END__ =pod =head1 VERSION $Id: CommandSpec.pm,v 1.4 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/DlfAnalyserSpec.pm0000644000175000017500000000723110460673256016376 00000000000000package Lire::Config::DlfAnalyserSpec; use strict; use base qw/Lire::Config::PluginSpec/; use Lire::PluginManager; use Lire::Config::OptionSpec; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::Config::DlfAnalyserSpec - PluginSpec to select an analyser. =head1 DESCRIPTION This Lire::Config::TypeSpec is a PluginSpec which can be used to select DlfAnalyser that should be used to create the Dlf records of an extended or derived schema. =head2 new( 'name' => $dst_stream_name, ['src_schema' => $from_schema]) The name of the type specification is the name of the schema for which the analyser is selected. If the 'src_stream' parameter is used, only analysers which uses that value as their src_schema() will be selected. The constructor will fill the PluginSpec automatically with the available options and it will be set the first analyser as default. =cut sub new { my $self = shift->SUPER::new( @_ ); my %args = @_; $self->add( new Lire::Config::OptionSpec( 'name' => 'none', 'summary' => N__( 'No analyser' ), 'description' => '' . join( "" ,N__( 'No analyser will be used.' )) . '' ) ); my $analysers = Lire::PluginManager->analysers_by_dst( $self->name() ); my $default = 'none'; foreach my $analyser ( sort { $a->name() cmp $b->name() } @$analysers ) { next if ( defined $args{'src_schema'} && $analyser->src_schema() ne $args{'src_schema'} ); $default = $analyser->name() if $default eq 'none'; $self->add( new Lire::Config::OptionSpec( 'name' => $analyser->name(), 'summary' => $analyser->title(), 'description' => $analyser->description(), ) ); } $self->default( $self->instance( 'value' => $default ) ); $self->{'_src_schema'} = $args{'src_schema'}; return $self; } =pod =head2 src_schema() Returns the src_schema() that should be used by the selected DlfAnalyser. If no particular schema is required, undef will be returned. =cut sub src_schema { return $_[0]{'_src_schema'}; } sub summary { return __x( 'Analyser to use for {schema} schema', 'schema' => $_[0]->name() ); } sub description { return '' . __x( q{Select the analyser to use to create {schema} DLF records. If you select 'none', no records will be created. Otherwise, the selected analyser will be run after each ImportJob that created records in the Dlf stream used by the analyser.}, 'schema' => $_[0]->name() ) . ''; } 1; __END__ =pod =head2 SEE ALSO Lire::Config::PluginSpec(3pm), Lire::Config::DlfStreamSpec(3pm) =head1 VERSION $Id: DlfAnalyserSpec.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/FileSpec.pm0000644000175000017500000000321510460673256015047 00000000000000package Lire::Config::FileSpec; use strict; =pod =head1 Lire::Config::FileSpec Type that represents a file name. Values of this type are names that refer to existing files. File values are only valid when the path they point to exists. =cut use base qw/Lire::Config::ScalarSpec/; use Lire::Utils qw(tilde_expand); use File::Spec; sub is_valid { my ( $self, $val ) = @_; return !$self->required() unless defined $val; my $file = $self->normalize( $val ); return 0 unless defined $file; return -f $file; } sub normalize { my ( $self, $val ) = @_; return undef unless defined $val; return File::Spec->canonpath( tilde_expand( $val )); } 1; __END__ =pod =head1 VERSION $Id: FileSpec.pm,v 1.3 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/DlfStreamSpec.pm0000644000175000017500000000624710460673256016061 00000000000000package Lire::Config::DlfStreamSpec; use strict; use base qw/Lire::Config::CompoundSpec/; use Lire::PluginManager; use Lire::Config::IntegerSpec; use Lire::Config::DlfAnalyserSpec; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::Config::DlfStreamSpec - Defines DlfStream configuration. =head1 DESCRIPTION This Lire::Config::TypeSpec is a CompoundSpec which hold the configuration related to a DlfStream.. =head2 new( 'name' => $dst_stream_name ) The name of the type specification is the name of the DlfStream which is configured. A DlfStreamSpec will define an integer component named 'keep_days' which hold the number of days of Dlf to keep. One component for each available extension schema is also defined. =cut sub new { my $self = shift->SUPER::new( @_ ); my $int = new Lire::Config::IntegerSpec( 'name' => 'keep_days', 'summary' => N__( 'Days of DLF to keep' ), 'description' => '' . join( "", N__( 'This parameter states how many days of DLF records you want to keep in the DlfStore. Records older than this number of days will be deleted. Use 0 to never expires records.' ) ) . '' ); $int->default( $int->instance( 'value' => 60 ) ); $self->add( $int ); foreach my $a ( @{ $self->_extension_schemas() } ) { $self->add( new Lire::Config::DlfAnalyserSpec( 'name' => $a, 'src_schema' => $self->name() ) ); } return $self; } sub _extension_schemas { my $self = $_[0]; my %schemas = (); foreach my $a ( @{Lire::PluginManager->analysers_by_src( $self->name() )} ) { $schemas{$a->dst_schema()} = 1; } return [ sort keys %schemas ]; } sub summary { return __x( 'Configuration for the {schema} DlfStream', 'schema' => $_[0]->name() ); } sub description { return '' . __x( 'This configures the analysers that should be run on this DlfStream as well as the number of days of data to keep.', 'schema' => $_[0]->name() ) . ''; } sub instance_class { return 'Lire::Config::Dictionary'; } 1; __END__ =pod =head2 SEE ALSO Lire::Config::DlfStreamsSpec(3pm), Lire::Config::DlfAnalyserSpec(3pm) =head1 VERSION $Id: DlfStreamSpec.pm,v 1.4 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/Dictionary.pm0000644000175000017500000001050210460673256015457 00000000000000package Lire::Config::Dictionary; use strict; use base qw/Lire::Config::Value/; use Carp; use Locale::TextDomain 'lire'; use Lire::Utils qw/ check_param check_object_param /; =pod =head1 NAME Lire::Config::Dictionary - Dictionary Value object. =head1 SYNOPSIS use Lire::Config::Dictionary; =head1 DESCRIPTION Configuration parameter which contain a bunch of named parameters other values accessible by name. This value is used for top-level configuration sets. =cut sub new { my $self = shift->SUPER::new(@_); check_object_param( $self->{'spec'}, 'spec', "Lire::Config::CompoundSpec"); $self->{'values'} = {} unless exists $self->{'values'}; return $self; } sub as_value { my $self = $_[0]; my $ret = {}; foreach my $param ( $self->spec()->components() ) { next if $param->obsolete(); $ret->{ $param->name() } = $self->get( $param->name() )->as_value(); } return $ret; } sub as_label { my $self = $_[0]; my $label = $self->{'spec'}->label_component(); if ( defined $label ) { my $label = $self->get( $label )->get() || ''; $label =~ s/(^\s*|\s*$)//g; $label = __( '-- unidentified --' ) if $label eq ''; return $label; } else { return $self; } } =pod =head2 is_set( $name ) Returns true if the parameter $name was set in this dictionary. =cut sub is_set { my ( $self, $name ) = @_; check_param( $name, 'name' ); croak "no parameter $name defined in ", $self->name() unless $self->spec()->has_component( $name ); return exists $self->{'values'}{$name}; } =pod =head2 get( $name ) Returns the Value object for the $name subparameter. An exception will be thrown if there is no subparameter named $name. =cut sub get { my ($self, $name) = @_; check_param( $name, 'name' ); croak "no parameter $name defined in ", $self->name() unless $self->spec()->has_component( $name ); unless ( exists $self->{'values'}{$name} ) { # Create empty var $self->{'values'}{$name} = $self->spec()->get( $name )->instance() } return $self->{'values'}{$name}; } =pod =head2 set( $value ) Sets a parameter in this dictionary. =cut sub set { my ( $self, $value ) = @_; check_object_param( $value, 'value', 'Lire::Config::Value' ); my $name = $value->name(); croak $self->name(), " cannot contains a ", $name, " parameter" unless $self->spec()->has_component( $name ); croak "$value is not a valid instance for parameter ", $name unless $self->spec()->get( $name )->is_instance( $value ); $self->{'values'}{$value->name() } = $value; return; } sub save_value { my ( $self, $fh, $indent, $xmlns ) = @_; while(my ($key, $val) = each(%{$self->{'values'}})) { $val->save_xml( $fh, $indent+1, $xmlns ); } } sub is_equals { my ( $self, $other ) = @_; return 0 unless $self->SUPER::is_equals( $other ); foreach my $param ( $self->spec()->components() ) { return 0 unless $self->get( $param->name() )->is_equals( $other->get( $param->name() ) ); } return 1; } sub is_valid { my $self = $_[0]; foreach my $comp ( $self->spec()->component_names() ) { my $elmnt = $self->get( $comp ); return 0 if $elmnt->spec()->required() && !$elmnt->is_valid(); } return 1; } 1; # whine, whine __END__ =pod =head1 AUTHORS Wessel Dankers Wolfgang Sourdeau Francis J. Lacoste =head1 VERSION $Id: Dictionary.pm,v 1.19 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ScalarSpec.pm0000644000175000017500000000326010460673256015375 00000000000000package Lire::Config::ScalarSpec; use strict; =pod =head1 Lire::Config::ScalarSpec Describes an abstract type for scalar configuration variables. =cut use base qw/Lire::Config::TypeSpec/; use Lire::Config::Scalar; use Carp; sub instance_class { return "Lire::Config::Scalar"; } =pod =head2 is_valid( $value ) Returns true if $value is appropriate for that parameter type. $value is the value has entered by the user for example. =cut sub is_valid { croak("is_valid() method not implemented in ", ref $_[0] ); } =pod =head2 normalize( $value ) This method returns the $value normalized for this type. =cut sub normalize { croak("normalize() method not implemented in ", ref $_[0] ); } 1; __END__ =pod =head1 VERSION $Id: ScalarSpec.pm,v 1.4 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/DlfSchemaSpec.pm0000644000175000017500000000563710460673256016030 00000000000000package Lire::Config::DlfSchemaSpec; use strict; =pod =head1 NAME Lire::Config::DlfSchemaSpec - SelectSpec for DlfSchema. =head1 DESCRIPTION This Lire::Config::TypeSpec is a SelectSpec which defines an option for each available DlfSchemas. =head2 new( 'name' => $name, [ 'superservices' => 1 ], ... ) Creates a new DlfSchemaSpec object. If superservices is set to 1, only superservices can be selected. =cut use base qw/ Lire::Config::SelectSpec /; use Carp; use Lire::DlfSchema; sub new { my $self = shift->SUPER::new( @_ ); my %args = @_; $self->superservices( $args{'superservices'} ) if exists $args{'superservices'}; return $self; } =pod =head2 supservices( [ $new_value ) Returns (and optionnally change) the setting of the superservices attributes. When this attribute is true, only superservices can be selected by this object. =cut sub superservices { my $self = $_[0]; $self->{'_superservices'} = $_[1] ? 1 : 0 if @_ == 2; return $self->{'_superservices'}; } sub is_valid { my ( $self, $val ) = @_; return !$self->required() unless $val; return Lire::DlfSchema->has_schema( $val ); } sub normalize { my ( $self, $val ) = @_; return $self->is_valid( $val ) ? $val : undef; } sub add { croak( 'Lire::Config::DlfSchemaSpec cannot contain any components' ); } sub options { my $self = $_[0]; my @names = ( $self->{'_superservices'} ? Lire::DlfSchema->superservices() : Lire::DlfSchema->schemas() ); my @options = (); foreach my $name ( sort @names ) { push @options, Lire::Config::DlfSchemaOptionSpec->new( 'name' => $name ); } return @options; } package Lire::Config::DlfSchemaOptionSpec; use base qw/Lire::Config::OptionSpec/; use Lire::DlfSchema; sub summary { return Lire::DlfSchema::load_schema( $_[0]->name() )->title(); } sub description { return Lire::DlfSchema::load_schema( $_[0]->name() )->description(); } 1; __END__ =pod =head1 VERSION $Id: DlfSchemaSpec.pm,v 1.10 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/Object.pm0000644000175000017500000000354610460673256014572 00000000000000package Lire::Config::Object; use strict; use base qw/Lire::Config::Dictionary/; use Carp; =pod =head1 NAME Lire::Config::Object - Configuration value which instantiates an object. =head1 SYNOPSIS use Lire::Config::Object; =head1 DESCRIPTION Configuration parameter which contain a bunch of named parameters values accessible by name. The as_value() method will return an object of the class defined in the specification. The object is instantiated using the new_from_config() method which should be defined in the specified class. =cut sub new { my $self = shift->SUPER::new(@_); croak "'spec' parameter should be a Lire::Config::ObjectSpec instance" unless $self->{'spec'}->isa( "Lire::Config::ObjectSpec" ); return $self; } sub as_value { my $self = $_[0]; eval "use " . $self->spec()->class() . ";"; die if $@; return $self->spec()->class()->new_from_config( $self ); } 1; # whine, whine __END__ =pod =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 VERSION $Id: Object.pm,v 1.5 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ReportSectionSpec.pm0000644000175000017500000000622210460673256016771 00000000000000package Lire::Config::ReportSectionSpec; use strict; use base qw/Lire::Config::ObjectSpec/; use Lire::Config::StringSpec; use Lire::Config::DlfSchemaSpec; use Lire::Config::XMLSpecListSpec; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::Config::ReportSectionSpec - Defines a report section. =head1 DESCRIPTION This Lire::Config::TypeSpec is a CompoundSpec which defines a report's section. =head2 new() Create a Lire::Config::SectionSpec object. =cut sub new { my $self = shift->SUPER::new( @_, 'label' => 'title', 'class' => 'Lire::ReportSection' ); $self->add( new Lire::Config::StringSpec( 'name' => 'title', 'summary' => N__( "Section's title" ), 'description' => '' . join( "", N__( "The section's title that will appear in the generated report." ) ) . '' ) ); $self->add( new Lire::Config::DlfSchemaSpec( 'name' => 'superservice', 'superservices' => 1, 'summary' => N__( "Section's Superservice" ), 'description' => '' . join( "", N__( 'The superservices that is used by this section.' ) ) . '' ) ); my $filters = new Lire::Config::XMLSpecListSpec( 'name' => 'filters', 'type' => 'filters', 'summary' => N__( "Section's filters" ), 'description' => '' . join( "", N__( 'List of filters that will be applied to this section.' ) ) . '' ); $self->add( $filters ); my $specs = new Lire::Config::XMLSpecListSpec( 'name' => 'specs', 'type' => 'reports', 'summary' => N__( "Section's content" ), 'description' => '' . join( "", N__( 'The chart and subreport that will be included in this section.' ) ) . '' ); $self->add( $specs ); return $self; } 1; __END__ =pod =head2 SEE ALSO Lire::Config::XMLSpecListSpec(3pm), Lire::Config::ReportSpec(3pm), Lire::ReportSection(3pm) =head1 VERSION $Id: ReportSectionSpec.pm,v 1.3 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/VariableIndex.pm0000644000175000017500000000651210460673257016076 00000000000000package Lire::Config::VariableIndex; use strict; use base qw/Lire::Config::Index/; use Lire::Utils qw/check_param check_object_param/; use Carp; =pod =head1 NAME Lire::Config::VariableIndex - Index of the available variables in a TableInfo =head1 SYNOPSIS =head1 DESCRIPTION This object make it possible to select a variable defined in a TableInfo (usually created from a Lire::ReportSpec or coming from a Lire::Report object). =head2 new( $table_info, [ $type ] ) Creates a new VariableIndex which wraps the $table_info Lire::Report::TableInfo object. The $type parameter can be either 'both', 'categorical' or 'numerical' depending on the kind of variables one wants to select. Default to 'both'. =head2 table_info() Returns the Lire::Report::TableInfo object wrapped by this Index. =head2 type() Returns the type attribute. =cut sub new { my ( $class, $info, $type ) = @_; check_object_param( $info, 'info', 'Lire::Report::TableInfo' ); $type ||= 'both'; check_param( $type, 'type', qr/^(both|categorical|numerical)$/, "'type' parameter should be either 'both', 'categorical' or 'numerical'" ); return bless { '_info' => $info, '_type' => $type, }, $class; } sub table_info { return $_[0]{'_info'}; } sub type { return $_[0]{'_type'}; } sub has_entry { my ( $self, $name ) = @_; check_param( $name, 'name' ); foreach my $col ( $self->{'_info'}->column_infos() ) { next if $self->{'_type'} ne 'both' && $col->class() ne $self->{'_type'}; return 1 if $name eq $col->name(); } return 0; } sub entries { my $self = $_[0]; my @entries = (); foreach my $col ( $self->{'_info'}->column_infos() ) { next if $self->{'_type'} ne 'both' && $col->class() ne $self->{'_type'}; push @entries, $col->name(); } return \@entries; } sub get_ref { my ( $self, $name ) = @_; check_param( $name, 'name' ); foreach my $col ( $self->{'_info'}->column_infos() ) { next if $self->{'_type'} ne 'both' && $col->class() ne $self->{'_type'}; return $col if $name eq $col->name(); } croak "no variable \"$name\""; } 1; __END__ =pod =head1 SEE ALSO Lire::ReportSpec(3pm) Lire::Report::TableInfo(3pm) Lire:Config::Index(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: VariableIndex.pm,v 1.3 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ReferenceSpec.pm0000644000175000017500000000607510460673256016075 00000000000000package Lire::Config::ReferenceSpec; use strict; use Lire::Config::Reference; =pod =head1 NAME Lire::Config::ReferenceSpec - SelectSpec which takes its options from an Index. =head1 DESCRIPTION This Lire::Config::TypeSpec is a SelectSpec which defines an option for each available entry in the Index named on its index property.. =head2 new( 'name' => $name, 'index' => $index, ... ) Creates a new ReferenceSpec object. The available options will be queried at run time under Index. =cut use base qw/ Lire::Config::SelectSpec /; use Carp; use Lire::Config::Index; use Lire::Utils qw/check_param/; sub new { my $self = shift->SUPER::new( @_ ); my %args = @_; $self->index( $args{'index'} ); return $self; } sub instance_class { return 'Lire::Config::Reference'; } =pod =head2 index( [ $new_index ) Returns (and optionnally change) the setting of the index attributes. =cut sub index { my ($self, $index) = @_; if ( @_ == 2 ) { check_param( $index, 'index' ); $self->{'_index'} = $_[1]; } return $self->{'_index'}; } sub add { croak( 'Lire::Config::ReferenceSpec cannot contain any components' ); } sub normalize { my ( $self, $val ) = @_; return undef unless defined $val; return undef unless Lire::Config::Index->has_index( $self->{'_index'} ); return Lire::Config::Index->get_index( $self->{'_index'} )->has_entry( $val ) ? $val : undef; } sub options { my $self = $_[0]; return () unless Lire::Config::Index->has_index( $self->{'_index'} ); my $index = Lire::Config::Index->get_index( $self->{'_index'} ); my @options = (); foreach my $name ( @{$index->entries()} ) { push @options, Lire::Config::OptionSpec->new( 'name' => $name ); } return @options; } sub as_value { my ( $self, $name ) = @_; return undef unless defined $name; return undef unless Lire::Config::Index->has_index( $self->{'_index'} ); my $index = Lire::Config::Index->get_index( $self->{'_index'} ); return undef unless $index->has_entry( $name ); return $index->get_ref( $name );; } 1; __END__ =pod =head1 SEE ALLO Lire::Config::ReportConfigIndex(3pm) Lire::Config::Index(3pm) =head1 VERSION $Id: ReferenceSpec.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/Build.pm0000644000175000017500000000725211677606155014426 00000000000000package Lire::Config::Build; use strict; require Exporter; use vars qw( $VERSION %ac @ISA @EXPORT_OK ); sub coalesce { my $x; $x = shift while @_ && !defined $x; return $x; } BEGIN { ($VERSION) = '$Revision: 1.9 $' =~ m!Revision: ([.\d]+)!; @ISA = qw(Exporter); @EXPORT_OK = qw(ac_info ac_path ac_flags); %ac = ( exec_prefix => '${prefix}', prefix => '/usr/local', program_transform_name => 's,x,x,', bindir => '${exec_prefix}/bin', sbindir => '${exec_prefix}/sbin', libexecdir => '${exec_prefix}/libexec', datadir => '${prefix}/share', sysconfdir => '${prefix}/etc', sharedstatedir => '${prefix}/com', localstatedir => '${prefix}/var', libdir => '${exec_prefix}/lib', includedir => '${prefix}/include', oldincludedir => '/usr/include', infodir => '${prefix}/share/info', mandir => '${prefix}/share/man', INSTALL_PROGRAM => '${INSTALL}', INSTALL_SCRIPT => '${INSTALL}', INSTALL_DATA => '${INSTALL} -m 644', PACKAGE => 'lire', VERSION => '2.1.1', SHELL => '/bin/bash', CFLAGS => '@CFLAGS@', CPPFLAGS => '@CPPFLAGS@', CXXFLAGS => '@CXXFLAGS@', FFLAGS => '@FFLAGS@', DEFS => '-DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"lire\" -DVERSION=\"2.1.1\"', LDFLAGS => '@LDFLAGS@', LIBS => '', PERL => '/usr/bin/perl', LR_PERL5LIB => '/usr/local/share/perl5', GZIP => '/bin/gzip', SENDMAIL => '/usr/sbin/sendmail', PLOTICUS => '/usr/bin/ploticus', TAR => '/bin/tar', GHOSTSCRIPT => '/usr/bin/gs', LR_ARCHIVEDIR => '/usr/local/var/lib/lire/data', ); # calculate the transitive closure of any substitutions my $changed; do { $changed = 0; while(my ($k, $v) = each(%ac)) { $changed ||= $ac{$k} =~ s/\$\{([^}]+)\}/coalesce($ac{$1}, $ENV{$1}, '')/e; $changed ||= $ac{$k} =~ s/\$([A-Za-z][A-Za-z0-9_]*)/coalesce($ac{$1}, $ENV{$1}, '')/e; } } while($changed); } sub ac_info { return $ac{$_[0]}; } sub ac_path { return join('/', map { ac_info($_) } @_); } sub ac_flags { return join(' ', map { ac_info($_) } @_); } # keep perl happy 1; __END__ =pod =head1 NAME Lire::Config::Build - Look up build-time information =head1 SYNOPSIS This module provides build-time information to the configuration module. It is primarily intended to be used internally by the configuration module but can be used elsewhere as well. Consider using the proper configuration though, since the user may wish to override certain parameters. =head1 DESCRIPTION =head1 VERSION $Id: Build.pm.in,v 1.9 2011/11/15 16:33:00 wraay Exp $ =head1 COPYRIGHT Copyright (C) 2001 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Wessel Dankers =cut # Local Variables: # mode: cperl # End: lire-2.1.1/all/lib/Lire/Config/Build.pm.in0000644000175000017500000000670211677604544015032 00000000000000package Lire::Config::Build; use strict; require Exporter; use vars qw( $VERSION %ac @ISA @EXPORT_OK ); sub coalesce { my $x; $x = shift while @_ && !defined $x; return $x; } BEGIN { ($VERSION) = '$Revision: 1.9 $' =~ m!Revision: ([.\d]+)!; @ISA = qw(Exporter); @EXPORT_OK = qw(ac_info ac_path ac_flags); %ac = ( exec_prefix => '@exec_prefix@', prefix => '@prefix@', program_transform_name => '@program_transform_name@', bindir => '@bindir@', sbindir => '@sbindir@', libexecdir => '@libexecdir@', datadir => '@datadir@', sysconfdir => '@sysconfdir@', sharedstatedir => '@sharedstatedir@', localstatedir => '@localstatedir@', libdir => '@libdir@', includedir => '@includedir@', oldincludedir => '@oldincludedir@', infodir => '@infodir@', mandir => '@mandir@', INSTALL_PROGRAM => '@INSTALL_PROGRAM@', INSTALL_SCRIPT => '@INSTALL_SCRIPT@', INSTALL_DATA => '@INSTALL_DATA@', PACKAGE => '@PACKAGE@', VERSION => '@VERSION@', SHELL => '@SHELL@', CFLAGS => '@CFLAGS@', CPPFLAGS => '@CPPFLAGS@', CXXFLAGS => '@CXXFLAGS@', FFLAGS => '@FFLAGS@', DEFS => '@DEFS@', LDFLAGS => '@LDFLAGS@', LIBS => '@LIBS@', PERL => '@PERL@', LR_PERL5LIB => '@LR_PERL5LIBDIR@', GZIP => '@GZIP@', SENDMAIL => '@SENDMAIL@', PLOTICUS => '@PLOTICUS@', TAR => '@TAR@', GHOSTSCRIPT => '@GHOSTSCRIPT@', LR_ARCHIVEDIR => '@LR_ARCHIVEDIR@', ); # calculate the transitive closure of any substitutions my $changed; do { $changed = 0; while(my ($k, $v) = each(%ac)) { $changed ||= $ac{$k} =~ s/\$\{([^}]+)\}/coalesce($ac{$1}, $ENV{$1}, '')/e; $changed ||= $ac{$k} =~ s/\$([A-Za-z][A-Za-z0-9_]*)/coalesce($ac{$1}, $ENV{$1}, '')/e; } } while($changed); } sub ac_info { return $ac{$_[0]}; } sub ac_path { return join('/', map { ac_info($_) } @_); } sub ac_flags { return join(' ', map { ac_info($_) } @_); } # keep perl happy 1; __END__ =pod =head1 NAME Lire::Config::Build - Look up build-time information =head1 SYNOPSIS This module provides build-time information to the configuration module. It is primarily intended to be used internally by the configuration module but can be used elsewhere as well. Consider using the proper configuration though, since the user may wish to override certain parameters. =head1 DESCRIPTION =head1 VERSION $Id: Build.pm.in,v 1.9 2011/11/15 16:33:00 wraay Exp $ =head1 COPYRIGHT Copyright (C) 2001 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Wessel Dankers =cut # Local Variables: # mode: cperl # End: lire-2.1.1/all/lib/Lire/Config/SpecParser.pm0000644000175000017500000002034010460673256015422 00000000000000package Lire::Config::SpecParser; use strict; use Lire::Config::TypeSpec; use Lire::Utils qw/ check_param /; use Lire::Error qw/directory_not_readable/; use base qw/Lire::DocBookParser Lire::Config::Parser/; use Carp; =pod =head1 NAME Lire::Config::SpecParser - Create configuration specification from XML files =head1 SYNOPSIS use Lire::Config::SpecParser; my $parser = new Lire::Config::SpecParser; my $spec = $parser->parsefile( 'spec.xml' ); $parser->merge_specifications_dir( '/etc/lire/config' ); my $spec = $parser->configspec(); =head1 DESCRIPTION This is an Lire::XMLParser which can build Lire::Config::ConfigSpec objects from an XML file. =cut sub namespaces { my $self = $_[0]; return { %{$self->Lire::Config::Parser::namespaces()}, 'http://www.logreport.org/LRCSML/' => 'lrcsml' }; } my %elements2class = ( 'lrcsml:boolean' => 'Lire::Config::BooleanSpec', 'lrcsml:command' => 'Lire::Config::CommandSpec', 'lrcsml:dlf-converter' => 'Lire::Config::DlfConverterSpec', 'lrcsml:dlf-schema' => 'Lire::Config::DlfSchemaSpec', 'lrcsml:dlf-streams' => 'Lire::Config::DlfStreamsSpec', 'lrcsml:directory' => 'Lire::Config::DirectorySpec', 'lrcsml:executable' => 'Lire::Config::ExecutableSpec', 'lrcsml:file' => 'Lire::Config::FileSpec', 'lrcsml:integer' => 'Lire::Config::IntegerSpec', 'lrcsml:list' => 'Lire::Config::ListSpec', 'lrcsml:object' => 'Lire::Config::ObjectSpec', 'lrcsml:option' => 'Lire::Config::OptionSpec', 'lrcsml:output-format' => 'Lire::Config::OutputFormatSpec', 'lrcsml:plugin' => 'Lire::Config::PluginSpec', 'lrcsml:record' => 'Lire::Config::RecordSpec', 'lrcsml:reference' => 'Lire::Config::ReferenceSpec', 'lrcsml:report-config' => 'Lire::Config::ReportSpec', 'lrcsml:select' => 'Lire::Config::SelectSpec', 'lrcsml:string' => 'Lire::Config::StringSpec', ); my @scalar_mix = qw/ lrcsml:boolean lrcsml:command lrcsml:directory lrcsml:dlf-converter lrcsml:dlf-schema lrcsml:dlf-streams lrcsml:executable lrcsml:output-format lrcsml:report-config lrcsml:reference lrcsml:file lrcsml:integer lrcsml:string /; my @compound_mix = qw/ lrcsml:list lrcsml:record lrcsml:object /; my @specs_mix = ( qw/ lrcsml:select lrcsml:plugin/, @scalar_mix, @compound_mix ), my @infos_mix = qw/lrcsml:summary lrcsml:description/; my %spec = ( 'lrcsml:config-spec' => [ @specs_mix ], 'lrcsml:summary' => { 'start' => 'collector_start', 'char' => 'collector_char', 'end' => 'summary_end', 'content' => [ 'PCDATA' ], }, 'lrcsml:description' => { 'start' => 'dbk_init', 'char' => 'dbk_element_char', 'end' => 'description_end', 'content' => [ @Lire::DocBookParser::top_levels ], }, 'lrcsml:select' => { 'start' => 'spec_start', 'end' => 'spec_end', 'content' => [ @infos_mix, 'lrcsml:option', 'lrcml:param' ] }, 'lrcsml:plugin' => { 'start' => 'spec_start', 'end' => 'spec_end', 'content' => [ @infos_mix, 'lrcsml:option', 'lrcml:param' ] }, 'lrcsml:option' => { 'start' => 'spec_start', 'end' => 'spec_end', 'content' => [ @infos_mix ] }, ); foreach my $name ( @scalar_mix ) { $spec{$name} = { 'start' => 'spec_start', 'end' => 'spec_end', 'content' => [ @infos_mix, 'lrcml:param' ] }; } foreach my $name ( @compound_mix ) { $spec{$name} = { 'start' => 'spec_start', 'end' => 'spec_end', 'content' => [ @infos_mix, @specs_mix, 'lrcml:param' ] }; } sub elements_spec { my $self = $_[0]; return { %{$self->Lire::Config::Parser::elements_spec()}, %{$self->Lire::DocBookParser::elements_spec()}, %spec, }; } =pod =head2 new() Creates a new parser object. =cut sub new { my $self = shift->SUPER::new( @_ ); $self->{'_spec'} = new Lire::Config::ConfigSpec(); return $self; } =pod =head2 configspec() Returns the Lire::Config::ConfigSpec object parsed. =cut sub configspec { return $_[0]->{'_spec'}; } =pod =head2 merge_specifications_dir( $dir ) Parses all the files ending in '.xml' in the $directory. The types defined in these files will be merged to the ConfigSpec object of this parser. =cut sub merge_specifications_dir { my ( $self, $dir ) = @_; check_param( $dir, 'dir' ); opendir(my $dh, $dir) or die directory_not_readable( $dir ), "\n"; foreach my $file (readdir($dh)) { next unless $file =~ /\.xml$/; $self->merge_specification("$dir/$file"); } close($dh); return; } =pod =head2 merge_specification_dir( $file ) Parses the $file XML file and merges the types it defines in the ConfigSpec defined by this parser. =cut sub merge_specification { my ( $self, $file ) = @_; check_param( $file, 'file' ); eval { $self->parsefile( $file ) }; croak "error while parsing XML Config spec $file: $@" if $@; return; } sub parse_start { my $self = $_[0]; $self->init_stack( 'config_spec' ); $self->init_stack( 'config_value' ); return; } sub parse_end { my $self = $_[0]; return $self->{'_spec'}; } sub ignorable_ws { my $self = $_[0]; $self->SUPER::dbk_element_char() if $self->within_element( 'lrcsml:description' ); return; } sub config_spec_start { my ( $self, $name, $attributes ) = @_; $self->stack_push( 'config_spec', $self->{'_spec'} ); return; } sub spec_start { my ( $self, $name, $attributes ) = @_; $self->error( "No Lire::Config:: class defined for element '$name'" ) unless exists $elements2class{$name}; my $spec = eval { no strict 'refs'; $elements2class{$name}->new( %$attributes ); }; $self->error( $@ ) if $@; my $parent = $self->stack_peek( 'config_spec' ); $parent->add( $spec ) if defined $parent; $self->stack_push( 'config_spec', $spec ); return; } sub spec_end { my ( $self, $name ) = @_; $self->stack_pop( 'config_spec' ); return; } sub current_param_spec { my ( $self, $name ) = @_; my $spec = $self->stack_peek( 'config_spec' ); return $spec->name() eq $name ? $spec : $spec->get( $name ); } sub summary_end { my ( $self, $name ) = @_; my $spec = $self->stack_peek( 'config_spec' ); $spec->summary( $self->get_collector( 'lrcsml:summary' ) ); return; } sub description_end { my ( $self, $name ) = @_; my $spec = $self->stack_peek( 'config_spec' ); $spec->description( $self->dbk_string() ); return; } sub param_end { my $self = $_[0]; my $spec = $self->stack_peek( 'config_spec' ); my $value = $self->stack_peek( 'config_value' ); $spec->default( $value ) if $self->stack_depth( 'config_value' ) == 1; $self->SUPER::param_end(); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Config::Parser(3pm), Lire::Config::TypeSpec(3pm), Lire::Config::ConfigSpec(3pm) =head1 AUTHORS Wessel Dankers Francis J. Lacoste =head1 VERSION $Id: SpecParser.pm,v 1.44 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002,2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/DirectorySpec.pm0000644000175000017500000000307710460673256016142 00000000000000package Lire::Config::DirectorySpec; use strict; =pod =head1 Lire::Config::DirectorySpec Type that represents a directory. Directory values are valid only when the path they point to exists. =cut use base qw/Lire::Config::ScalarSpec/; use Lire::Utils qw(tilde_expand); use File::Spec; sub is_valid { my ( $self, $val ) = @_; return !$self->required() unless defined $val; my $dir = $self->normalize( $val ); return -d $dir; } sub normalize { my ( $self, $val ) = @_; return undef unless defined $val; return File::Spec->canonpath( tilde_expand( $val ) ); } 1; __END__ =pod =head1 VERSION $Id: DirectorySpec.pm,v 1.3 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/Index.pm0000644000175000017500000000556310460673256014434 00000000000000package Lire::Config::Index; use strict; use Lire::Utils qw/ check_object_param /; use Carp; our %REGISTRY = (); =pod =head1 NAME Lire::Config::Index - Index registry and interface =head1 SYNOPSIS use base qw/Lire::Config::Index/; sub has_entry { my ($self, $name) = @_; ... } sub entries { my $self = $_[0]; ... } sub get_ref { my ($self, $name) = @_; ... } =head1 DESCRIPTION The Lire::Config::Index interface is used by the Lire::Config::ReferenceSpec(3pm) to validate and obtain referenced object. =head1 INDEX REGISTRY These are the class methods used to register and obtain Index objects. =head2 has_index( $name ) Returns true if an index was registered under $name. =head2 get_index( $name ) Retuurns the Index named $name. Croaks if no such index was registered. =head2 set_index( $name, $index ) Registers $index under $name. Replaces any previous index registered under the same name. =cut sub has_index { my ( $self, $name ) = @_; return defined $REGISTRY{$name}; } sub get_index { my ( $self, $name ) = @_; croak "no index registered under '$name'" unless $self->has_index( $name ); return $REGISTRY{$name}; } sub set_index { my ( $self, $name, $index ) = @_; check_object_param( $index, 'index', 'Lire::Config::Index' ) if defined $index; $REGISTRY{$name} = $index; return; } =pod =head1 INDEX INTERFACE =head2 has_entry( $name ) Should return true if $name is defined in this index. =head2 entries() Should return all the entries defined in the index. =head2 get_ref( $name ) Should return the object indexed under $name. An error should be thrown if there is no such entry.;. =cut sub has_entry { croak ref shift, "::has_entry is unimplemented"; } sub entries { croak ref shift, "::entries is unimplemented"; } sub get_ref { croak ref shift, "::get_ref is unimplemented"; } 1; __END__ =pod =head1 SEE ALSO Lire::Config::Reference(3pm) Lire::Config::ReferenceSpec(3pm) Lire:Config::ReportConfigIndex(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: Index.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ObjectSpec.pm0000644000175000017500000000315410460673256015400 00000000000000package Lire::Config::ObjectSpec; use strict; use base qw/ Lire::Config::CompoundSpec /; use Carp; use Lire::Config::Object; use Lire::Utils qw/ check_param /; =pod =head1 Lire::Config::ObjectSpec Describes a type of configuration variables that will be used to instantiate an object in a class which defines a new_from_config() constructor. =cut sub new { my ( $class, %args ) = @_; check_param( $args{'class'}, 'class' ); my $self = $class->SUPER::new( %args ); $self->{'class'} = $args{'class'}; return $self; } sub class { return $_[0]{'class'} } sub instance_class { return 'Lire::Config::Object'; } 1; __END__ =pod =head1 VERSION $Id: ObjectSpec.pm,v 1.5 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/Makefile.am0000644000175000017500000000505110114501706015035 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.22 2004/08/30 01:32:54 flacoste Exp $ ## Copyright (C) 2000-2003 Stichting LogReport Foundation LogReport@LogReport.org ## ## This file is part of Lire. ## ## Lire is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk SUBDIRS = allperllibdir = $(LR_PERL5LIBDIR)/Lire/Config pm_s = \ BasePluginSpec.pm \ BooleanSpec.pm \ Build.pm \ ChartSpec.pm \ ChartTypeSpec.pm \ CommandSpec.pm \ CompoundSpec.pm \ ConfigFile.pm \ ConfigSpec.pm \ Dictionary.pm \ DirectorySpec.pm \ DlfAnalyserSpec.pm \ DlfConverterSpec.pm \ DlfSchemaSpec.pm \ DlfStreamSpec.pm \ DlfStreamsSpec.pm \ ExecutableSpec.pm \ FileSpec.pm \ Index.pm \ IntegerSpec.pm \ List.pm \ ListSpec.pm \ Object.pm \ ObjectSpec.pm \ OptionSpec.pm \ OutputFormatSpec.pm \ Parser.pm \ Plugin.pm \ PluginSpec.pm \ RecordSpec.pm \ Reference.pm \ ReferenceSpec.pm \ ReportConfigIndex.pm \ ReportSectionSpec.pm \ ReportSpec.pm \ Scalar.pm \ ScalarSpec.pm \ SelectSpec.pm \ SpecParser.pm \ StringSpec.pm \ TypeSpec.pm \ VariableIndex.pm \ Value.pm \ XMLSpecListSpec.pm allperllib_DATA = $(pm_s) man_MANS = \ BasePluginSpec.3pm \ Build.3pm \ ChartSpec.3pm \ ChartTypeSpec.3pm \ ConfigFile.3pm \ DlfAnalyserSpec.3pm \ DlfConverterSpec.3pm \ DlfStreamSpec.3pm \ DlfStreamsSpec.3pm \ Dictionary.3pm \ Index.3pm \ List.3pm \ Object.3pm \ OutputFormatSpec.3pm \ Parser.3pm \ Plugin.3pm \ RecordSpec.3pm \ Reference.3pm \ ReferenceSpec.3pm \ ReportConfigIndex.3pm \ ReportSpec.3pm \ ReportSectionSpec.3pm \ Scalar.3pm \ SpecParser.3pm \ Value.3pm \ VariableIndex.3pm \ XMLSpecListSpec.3pm perlpackage = Lire::Config transform = s,^,$(perlpackage)::, EXTRA_DIST = $(pm_s) CLEANFILES = $(man_MANS) lire-2.1.1/all/lib/Lire/Config/Makefile.in0000644000175000017500000006373411677606132015100 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Build.pm.in $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/include/rules.mk subdir = all/lib/Lire/Config ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = Build.pm CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(allperllib_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" transform = s,^,$(perlpackage)::, ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done SUBDIRS = allperllibdir = $(LR_PERL5LIBDIR)/Lire/Config pm_s = \ BasePluginSpec.pm \ BooleanSpec.pm \ Build.pm \ ChartSpec.pm \ ChartTypeSpec.pm \ CommandSpec.pm \ CompoundSpec.pm \ ConfigFile.pm \ ConfigSpec.pm \ Dictionary.pm \ DirectorySpec.pm \ DlfAnalyserSpec.pm \ DlfConverterSpec.pm \ DlfSchemaSpec.pm \ DlfStreamSpec.pm \ DlfStreamsSpec.pm \ ExecutableSpec.pm \ FileSpec.pm \ Index.pm \ IntegerSpec.pm \ List.pm \ ListSpec.pm \ Object.pm \ ObjectSpec.pm \ OptionSpec.pm \ OutputFormatSpec.pm \ Parser.pm \ Plugin.pm \ PluginSpec.pm \ RecordSpec.pm \ Reference.pm \ ReferenceSpec.pm \ ReportConfigIndex.pm \ ReportSectionSpec.pm \ ReportSpec.pm \ Scalar.pm \ ScalarSpec.pm \ SelectSpec.pm \ SpecParser.pm \ StringSpec.pm \ TypeSpec.pm \ VariableIndex.pm \ Value.pm \ XMLSpecListSpec.pm allperllib_DATA = $(pm_s) man_MANS = \ BasePluginSpec.3pm \ Build.3pm \ ChartSpec.3pm \ ChartTypeSpec.3pm \ ConfigFile.3pm \ DlfAnalyserSpec.3pm \ DlfConverterSpec.3pm \ DlfStreamSpec.3pm \ DlfStreamsSpec.3pm \ Dictionary.3pm \ Index.3pm \ List.3pm \ Object.3pm \ OutputFormatSpec.3pm \ Parser.3pm \ Plugin.3pm \ RecordSpec.3pm \ Reference.3pm \ ReferenceSpec.3pm \ ReportConfigIndex.3pm \ ReportSpec.3pm \ ReportSectionSpec.3pm \ Scalar.3pm \ SpecParser.3pm \ Value.3pm \ VariableIndex.3pm \ XMLSpecListSpec.3pm perlpackage = Lire::Config EXTRA_DIST = $(pm_s) CLEANFILES = $(man_MANS) all: all-recursive .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/Lire/Config/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/Lire/Config/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Build.pm: $(top_builddir)/config.status $(srcdir)/Build.pm.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-man3: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list=''; test -n "$(man3dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } install-allperllibDATA: $(allperllib_DATA) @$(NORMAL_INSTALL) test -z "$(allperllibdir)" || $(MKDIR_P) "$(DESTDIR)$(allperllibdir)" @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(allperllibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(allperllibdir)" || exit $$?; \ done uninstall-allperllibDATA: @$(NORMAL_UNINSTALL) @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(allperllibdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(allperllibdir)" && rm -f $$files # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-recursive all-am: Makefile $(MANS) $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-allperllibDATA install-man install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man3 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-allperllibDATA uninstall-man uninstall-man: uninstall-man3 .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \ ctags-recursive install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am check-local clean clean-generic \ ctags ctags-recursive distclean distclean-generic \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-allperllibDATA install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man3 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-allperllibDATA uninstall-am uninstall-man \ uninstall-man3 .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lire-2.1.1/all/lib/Lire/Config/BooleanSpec.pm0000644000175000017500000000315210460673256015547 00000000000000package Lire::Config::BooleanSpec; =pod =head1 NAME Lire::Config::BooleanSpec - Type that represents a boolean =head1 DESCRIPTION Values of this type are yes/no values. These values are normalized to 0 or 1. =cut use base qw/Lire::Config::ScalarSpec/; sub is_valid { my ( $self, $val ) = @_; return !$self->required() unless defined $val; return 1 if !$val; return scalar $val =~ /^(0|1|f|false|true|t|no|off|disabled|enabled|yes|on)$/i; } sub normalize { my ( $self, $val ) = @_; return undef unless defined $val; return ! 1 if !$val; return ! scalar $val =~ /^(0|f|false|no|off|disabled)$/i; } 1; __END__ =pod =head1 VERSION $Id: BooleanSpec.pm,v 1.3 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/Value.pm0000644000175000017500000001147210765035043014427 00000000000000package Lire::Config::Value; use strict; use Carp; use Lire::Utils qw/ deep_copy check_object_param /; # Load subclasses use Lire::Config::Scalar; use Lire::Config::List; use Lire::Config::Dictionary; use Lire::Config::ConfigFile; use Lire::Config::Object; use Lire::Config::Plugin; =pod =head1 NAME Lire::Config::Value - Lire value containers for configuration variables =head1 SYNOPSIS use base qw/ Lire::Config::Value /; =head1 DESCRIPTION Value containers for configuration variables. This is the abstract superclass for the other Lire::Config::Value classes. =head2 new( ['spec' => $spec], ... ) This is the constructor for the value object. Lire::Config::Value objects should be instantiated from the instance() method defined in the TypeSpec object. =cut sub new { my ( $class, %args ) = @_; if ( ref $class ) { check_object_param( $class, 'proto', 'Lire::Config::Value' ); return $class->clone(); } else { check_object_param( $args{'spec'}, 'spec', 'Lire::Config::TypeSpec' ); return bless { 'spec' => $args{'spec'}, }, $class; } } =pod =head2 name() Returns this configuration parameter's name. =cut sub name { return $_[0]->{'spec'}->name(); } =pod =head2 spec() Returns the specification for this parameter. =cut sub spec { return $_[0]{'spec'}; } =pod =head2 summary() Returns the specification's summary for this value. =cut sub summary { return $_[0]->{'spec'}->summary(); } =pod =head2 description() Returns the specification's description for this value. =cut sub description { return $_[0]->{'spec'}->description(); } =pod =head2 text_description() Returns the specification's description (formatted in plain text) for this value. =cut sub text_description { return $_[0]->{'spec'}->text_description(); } =pod =head2 as_value() Returns this value as a perl native value. This will be either a scalar value, or an hash or array references. The returned values should be normalized. =cut sub as_value { croak ref $_[0], "::as_value is unimplemented"; } =pod =head2 as_label() Return the label of this object for displaying in GUI's. =cut sub as_label { croak ref $_[0], "::as_label is unimplemented"; } =pod =head2 as_shell_var() Returns this configuration variable's value in a form that can be evaled in a shell script. =cut sub as_shell_var { return $_[0]->name() . q{="Variable's type not supported in shell"}; } =pod =head2 clone() Return a deep_copie'd value of this instance. The reference to the spec is kept but is not copied. =cut sub clone { return deep_copy( $_[0], [ 'Lire::Config::TypeSpec' ] ); } =pod =head2 is_equals( $param ) Returns if the $param instance is identifcal to this one. =cut sub is_equals { my ( $self, $param ) = @_; check_object_param( $param, 'param', 'Lire::Config::Value' ); return 1 if $param eq $self; return $self->{'spec'} eq $param->{'spec'}; } =pod =head2 is_valid() Checks that the current value is valid according to the specification. =cut sub is_valid { croak("is_valid() method not implemented in ", ref $_[0] ); } =pod =head2 is_default() Returns true if this value is equals to its specification's default. =cut sub is_default { my $self = $_[0]; return $self->{'spec'}->has_default() && $self->is_equals( $self->{'spec'}->default() ); } =pod =head2 save_xml( $fh ) Writes an XML configuration of the variable recursively on $fh. =cut sub save_xml { my ( $self, $fh, $indent, $xmlns ) = @_; $indent ||= 0; $xmlns ||= ''; return if $self->is_default() || $self->spec()->obsolete(); print $fh ' 'x$indent, "<${xmlns}param name=\"", $self->name() , '">', "\n"; $self->save_value( $fh, $indent, $xmlns ); print $fh ' 'x$indent, "\n"; return; } 1; # whine, whine __END__ =pod =head1 AUTHORS Wessel Dankers Francis J. Lacoste Wolfgang Sourdeau =head1 VERSION $Id: Value.pm,v 1.18 2008/03/09 19:27:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/Plugin.pm0000644000175000017500000000747010460672575014625 00000000000000package Lire::Config::Plugin; use strict; use base qw/Lire::Config::Dictionary/; use Lire::Config; use Lire::Config::RecordSpec; use Lire::Config::Dictionary; use Carp; =pod =head1 NAME Lire::Config::Plugin - Value object for plugin configuration. =head1 SYNOPSIS use Lire::Config::Plugin; =head1 DESCRIPTION This configuration object hold the name of a selected plugin as well as its options. =cut sub new { my $self = shift->SUPER::new( @_ ); my %args = @_; $self->set_plugin( $args{'value'} ) unless ( exists $self->{'_plugin'} && ! defined $args{'value'} ); return $self; } =pod =head2 get_plugin() Returns the currently selected plugin. =cut sub get_plugin { return $_[0]{'_plugin'}; } =pod =head2 set_plugin( $plugin ) Changes the selected plugin. If the selected plugin is changed, a new property set will be created from the plugin's defined properties. =cut sub set_plugin { my ( $self, $plugin ) = @_; my $old_plugin = $self->{'_plugin'}; $self->{'_plugin'} = $plugin; my $spec = $self->get_properties_spec(); $self->{'_properties'} = $spec->instance() unless ( defined $plugin && defined $old_plugin && $plugin eq $old_plugin ); return; } =pod =head2 get_properties_spec() Returns the TypeSpec that is used to specify the plugin's properties. This method will return an empty RecordSpec when the plugin didn't define any properties. One can also use the has_properties() method to check if the Plugin defined configuration properties. =cut sub get_properties_spec { my $self = $_[0]; return $self->spec()->get_properties_spec( $self->{'_plugin'} ); } =pod =head2 has_properties() Returns a boolean value indicating whether the current plugin is configurable. =cut sub has_properties { return $_[0]->get_properties_spec()->components() > 0; } =pod =head2 get_properties() Returns the Lire::Config::Dictionary object which hold the plugin configuration. =cut sub get_properties { return $_[0]{'_properties'}; } =pod =head2 as_value() Returns an hash reference with two keys : 'plugin' which contains the selected plugin and 'properties' which is an hash reference containing the plugin's properties. =cut sub as_value { return { 'plugin' => $_[0]->{'_plugin'}, 'properties' => $_[0]->{'_properties'}->as_value() }; } =pod =head2 get( $name ) Delegates to the Dictionary which contains the plugin's properties. =cut sub get { return shift->{'_properties'}->get( @_ ); } =pod =head2 set( $name, $value ) Delegates to the Dictionary which contains the plugin's properties. =cut sub set { return shift->{'_properties'}->set( @_ ); } =pod =head2 is_set( $name ) Delegates to the Dictionary which contains the plugin's properties. =cut sub is_set { return shift->{'_properties'}->is_set( @_ ); } sub is_equals { my ( $self, $other ) = @_; return 0 unless $self->Lire::Config::Value::is_equals( $other ); no warnings 'uninitialized'; return 0 unless $self->{'_plugin'} eq $other->{'_plugin'}; return $self->{'_properties'}->is_equals( $other->{'_properties'} ); } sub is_valid { my $self = $_[0]; return ( $self->spec()->is_valid( $self->{'_plugin'} ) && $self->get_properties()->is_valid() ); } sub save_xml { my ( $self, $fh, $indent, $xmlns ) = @_; $indent ||= 0; $xmlns ||= ''; return unless ( defined $self->{'_plugin'} ); return if $self->is_default() || $self->spec()->obsolete(); print $fh ' ' x $indent, "<${xmlns}param name=\"", $self->name(), '" value="', $self->{'_plugin'}, '">', "\n"; my $spec = $self->get_properties_spec(); foreach my $comp ( $spec->components() ) { $self->get( $comp->name() )->save_xml( $fh, $indent + 1, $xmlns ); } print $fh ' ' x $indent, "\n"; } 1; lire-2.1.1/all/lib/Lire/Config/IntegerSpec.pm0000644000175000017500000000300510460673256015562 00000000000000package Lire::Config::IntegerSpec; use strict; =pod =head1 Lire::Config::IntegerSpec Type that represents an integer number. Values of this type are simple integer numbers with a range of -2147483648 to 2147483647. =cut use base qw/Lire::Config::ScalarSpec/; sub is_valid { my ( $self, $val ) = @_; return !$self->required() unless defined $val; return scalar $val =~ /^-?[0-9_]+$/; } sub normalize { my ( $self, $val ) = @_; return undef unless defined $val; no warnings 'numeric'; return int($val); } 1; __END__ =pod =head1 VERSION $Id: IntegerSpec.pm,v 1.4 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/List.pm0000644000175000017500000001302710460673256014272 00000000000000package Lire::Config::List; use strict; use base qw/ Lire::Config::Value /; use Carp; use Lire::Utils qw/ check_param check_object_param /; =pod =head1 NAME Lire::Config::List - List Value Object. =head1 DESCRIPTION Used for configuration parameters which contains a list of values. =cut sub new { my $self = shift->SUPER::new( @_ ); check_object_param( $self->{'spec'}, 'spec', 'Lire::Config::ListSpec' ); $self->{'elements'} = [] unless ( exists $self->{'elements'} ); return $self; } sub as_value { return [ map { $_->as_value() } @{$_[0]->{'elements'}} ]; } =pod =head2 elements() Returns this list's values as an array of Lire::Config::Value object. =cut sub elements { return @{$_[0]->{'elements'}}; } =pod =head2 get( $idx ) Returns the value stored at index $idx of this list. An exception is thrown if the index is out-of-bounds. =cut sub get { my ( $self, $idx ) = @_; check_param( $idx, 'idx', qr/^-?\d+$/, "'idx' parameter should be an integer" ); croak "index out of bounds: $idx" unless $idx >= 0 ? ( $idx < @{$self->{'elements'}} ): ( abs($idx)-1 < @{$self->{'elements'}} ); return $self->{'elements'}[$idx]; } =pod =head2 remove( $idx ) Removes the value stored at index $idx of this list. An exception is thrown if the index is out-of-bounds. It returns the deleted element. =cut sub remove { my ( $self, $idx ) = @_; check_param( $idx, 'idx', qr/^-?\d+$/, "'idx' parameter should be an integer" ); croak "index out of bounds: $idx" unless ( $idx >= 0 ? ( $idx < @{$self->{'elements'}} ) : ( abs($idx)-1 < @{$self->{'elements'}} ) ); return splice(@{$self->{'elements'}}, $idx, 1); } =pod =head2 clear() Removes all elements from this list =cut sub clear { my $self = $_[0]; $self->{'elements'} = []; return; } =pod =head2 append( $val, [ $idx ] ) Adds $val to after element $idx. If $idx is omitted, the element will be added at the end of the array. A negative index is interpreted relative to the end of the array. =cut sub append { my ( $self, $value, $idx ) = @_; check_object_param( $value, 'value', 'Lire::Config::Value' ); $self->check_idx( $idx ) if defined $idx; my $value_name = $value->name(); croak $self->name(), " cannot contains ", $value_name, " parameters" unless $self->spec()->has_component( $value_name ); croak "$value is not a valid instance for component ", $value_name unless $self->spec()->get( $value_name )->is_instance( $value ); if ( defined $idx ) { $idx = $idx == -1 ? $#{$self->{'elements'}} + 1 : $idx+1; splice @{$self->{'elements'}}, $idx, 0, $value; } else { push @{$self->{'elements'}}, $value; } return; } sub check_idx { my ( $self, $idx ) = @_; croak "not an integer: $idx" unless $idx =~ /^-?\d+$/; croak "index out of bounds: $idx" unless $idx >= 0 ? ( $idx < @{$self->{'elements'}} ): ( abs($idx)-1 < @{$self->{'elements'}} ); return; } =pod =head2 move( $idx, $new_idx ) Moves element $idx at position $new_idx. Indices can be negative and are interpreted as position relative to the end of the array. =cut sub move { my ( $self, $idx, $new_idx ) = @_; $self->check_idx( $idx ); $self->check_idx( $new_idx ); $idx = @{$self->{'elements'}} + $idx if $idx < 0; $new_idx = @{$self->{'elements'}} + $new_idx if $new_idx < 0; return if $idx == $new_idx; my $elmnt = splice @{$self->{'elements'}}, $idx, 1; splice @{$self->{'elements'}}, $new_idx, 0, $elmnt; return; } =pod =head2 set( $idx, $value ) Replaces value at index $idx with $value. =cut sub set { my ( $self, $idx, $value ) = @_; check_param( $idx, 'idx' ); check_param( $value, 'value' ); $self->check_idx( $idx ); $self->{'elements'}[$idx] = $value; return; } sub is_equals { my ( $self, $other ) = @_; return 0 unless $self->SUPER::is_equals( $other ); return 0 unless @{$self->{'elements'}} == @{$other->{'elements'}}; for ( my $i=0; $i < @{$self->{'elements'}}; $i++ ) { return 0 unless $self->{'elements'}[$i]->is_equals( $other->{'elements'}[$i] ); } return 1; } sub is_valid { my $self = $_[0]; foreach my $elmnt ( $self->elements() ) { return 0 if $elmnt->spec()->required() && !$elmnt->is_valid(); } return 1; } sub save_value { my ( $self, $fh, $indent, $xmlns ) = @_; foreach my $val (@{$self->{'elements'}}) { $val->save_xml( $fh, $indent+1, $xmlns ); } return; } 1; # whine, whine __END__ =pod =head1 AUTHOR Wessel Dankers =head1 VERSION $Id: List.pm,v 1.16 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/DlfConverterSpec.pm0000644000175000017500000000240210460673256016562 00000000000000package Lire::Config::DlfConverterSpec; use strict; =pod =head1 NAME Lire::Config::DlfConverterSpec - PluginSpec for DlfConverters. =head1 DESCRIPTION This is a Lire::Config::PluginSpec object that can be used to select any registered Lire::DlfConverter. =cut use base qw/Lire::Config::BasePluginSpec/; sub plugin_type { return "dlf_converter"; } 1; __END__ =pod =head1 VERSION $Id: DlfConverterSpec.pm,v 1.6 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ChartTypeSpec.pm0000644000175000017500000000235710460673256016101 00000000000000package Lire::Config::ChartTypeSpec; use strict; =pod =head1 NAME Lire::Config::ChartTypeSpec - PluginSpec for ChartType. =head1 DESCRIPTION This is a Lire::Config::PluginSpec object that can be used to select any registered Lire::ChartType. =cut use base qw/Lire::Config::BasePluginSpec/; sub plugin_type { return "chart_type"; } 1; __END__ =pod =head1 VERSION $Id: ChartTypeSpec.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ConfigSpec.pm0000644000175000017500000000251310460672575015400 00000000000000package Lire::Config::ConfigSpec; use strict; use base qw/ Lire::Config::CompoundSpec /; use Lire::Utils qw/ check_param /; =pod =head1 Lire::Config::ConfigSpec Describes a type of configuration variables that contain a configuration. That is, not the entire configuration but a part, such as a single template or the list of global configuration items. =cut sub new { return shift->SUPER::new( 'name' => 'config', @_ ); } sub instance_class { return "Lire::Config::Dictionary"; } =pod =head2 components_by_section( $section ) Returns in an array ref all the contained parameter specifications that are in the requested section. The parameters are sorted alphabetically. =cut sub components_by_section { my ( $self, $section) = @_; check_param( $section, 'section' ); my $comps = []; my @components = $self->components(); foreach my $comp ( @components ) { push @$comps, $comp if ( defined $comp->{'section'} && $section eq $comp->{'section'} ); } return $comps; } =pod =head2 xml_file( [ $file ] ) Returns the XML filename from which this specification was loaded. If the $file parameter is set, the associated filename will be changed. =cut sub xml_file { my ( $self, $file ) = @_; $self->{'xml_file'} = $file if defined $file; return $self->{'xml_file'}; } 1; lire-2.1.1/all/lib/Lire/Config/Parser.pm0000644000175000017500000001264310460673256014616 00000000000000package Lire::Config::Parser; use strict; use base qw/Lire::XMLParser/; use Lire::Utils qw/ check_object_param /; use Lire::Config::TypeSpec; use Lire::Config::Value; use Carp; =pod =head1 NAME Lire::Config::Parser - Creates a Lire::Config::ConfigFile object from XML =head1 SYNOPSIS use Lire::Config; use Lire::Config::Parser; my $parser = new Lire::Config::Parser( 'spec' => Lire::Config->config_spec()); my $conf = $parser->parsefile( 'config.xml' ); =head1 DESCRIPTION Rather straightforward XML parser that follows the configuration specification to parse an XML file. =head2 new( 'spec' => $spec ) Creates a parser object which will parse configuration file which validates against the Lire::Config::ConfigSpec specification $spec. =cut sub new { my $self = shift->SUPER::new(); my %args = @_; check_object_param( $args{'spec'}, 'spec', 'Lire::Config::ConfigSpec' ); $self->{'spec'} = $args{'spec'}; return $self; } sub namespaces { return { 'http://www.logreport.org/LRCML/' => 'lrcml' }; } sub elements_spec { return { 'lrcml:config' => [ 'lrcml:global', 'lrcml:param' ], 'lrcml:global' => [ 'lrcml:param' ], 'lrcml:param' => [ 'PCDATA', 'lrcml:param' ], }; } =pod =head2 load_config_file( $file ) Parses the $file XML file and returns a Lire::Config::ConfigFile object representing it. =cut sub load_config_file { my ( $self, $file ) = @_; $self->{'filename'} = $file; my $conf = eval { $self->parsefile( $file ) };; croak "error while parsing XML Config $file: $@" if $@; return $conf; } sub parse_start { my $self = $_[0]; $self->{'conf'} = new Lire::Config::ConfigFile( 'spec' => $self->{'spec'}, 'filename' => $self->{'filename'}, ); $self->init_stack( 'config_spec' ); $self->init_stack( 'config_value' ); return; } sub parse_end { my $self = $_[0]; return $self->{'conf'}; } sub param_char { my ( $self, $text ) = @_; $self->collect( 'lrcml:param' . $self->depth(), $text ); return; } sub current_param_spec { my ( $self, $name ) = @_; return $self->stack_peek( 'config_spec' )->get( $name ); } sub param_start { my ( $self, $param, $attr ) = @_; $self->error( " must be the root element" ) if $self->is_stack_empty( 'config_spec' ); my $spec = $self->current_param_spec( $attr->{'name'} ); my $value = $spec->instance( %$attr ); unless ( $self->is_stack_empty( 'config_value' ) ) { my $parent_value = $self->stack_peek( 'config_value' ); if( $parent_value->isa( "Lire::Config::List" ) ) { $parent_value->append( $value ); } elsif ( $parent_value->isa("Lire::Config::Dictionary") ) { $parent_value->set($value); } else { $self->error( "unknown parameter container type: $parent_value" ); } } $spec = $value->get_properties_spec() if $value->isa( 'Lire::Config::Plugin' ); # Remove any default since the value is redefined. $value->clear() if $value->isa( 'Lire::Config::List' ); $self->stack_push( 'config_spec', $spec ); $self->stack_push( 'config_value', $value ); $self->init_collector( 'lrcml:param' . ($self->depth() + 1) ); return; } sub param_end { my $self = $_[0]; $self->stack_pop( 'config_spec' ); my $value = $self->stack_pop( 'config_value' ); if( $value->isa( "Lire::Config::Scalar" ) ) { local $SIG{'__WARN__'} = sub {}; my $text = $self->get_collector( 'lrcml:param' . ($self->depth() + 1)); $value->set( $text ) unless $text eq '' && $value->get() ne ''; } return; } sub config_start { my ( $self, $name, $attr ) = @_; $self->error( " must be the root element" ) unless $self->is_stack_empty( 'config_spec' ); my $global_conf = $self->{'spec'}->instance(); $self->{'conf'}->global( $global_conf ); $self->stack_push( 'config_spec', $self->{'spec'} ); $self->stack_push( 'config_value', $global_conf ); return; } sub config_end { my $self = $_[0]; $self->stack_pop( 'config_spec' ); $self->stack_pop( 'config_value' ); $self->error( " must be the root element" ) unless $self->is_stack_empty( 'config_spec' ); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Config::ConfigFile(3pm), Lire::Config::SpecParser(3pm), Lire::Config::ConfigSpec(3pm) =head1 AUTHORS Wessel Dankers Francis J. Lacoste =head1 VERSION $Id: Parser.pm,v 1.49 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ConfigFile.pm0000644000175000017500000001257410460673256015372 00000000000000package Lire::Config::ConfigFile; use strict; use base qw/ Lire::Config::Dictionary /; use Carp; use Lire::Config::Parser; use Lire::I18N qw/ set_fh_encoding /; use Lire::Utils qw/ check_param check_object_param /; =pod =head1 NAME Lire::Config::ConfigFile - Class for configuration file manipulation. =head1 SYNOPSIS use Lire::Config::ConfigFile; =head1 DESCRIPTION Object representing a Lire configuration file. =head2 new( 'filename' => $file, spec => $config_spec ) Creates a new Lire::Config::ConfigFile object. The constructor takes two parameters: =over =item filename The file form where the configuration was stored or was loaded from. =item spec The Lire::Config::TypeSpec object to which this configuration adheres. =end =cut sub new { my ( $proto, %args ) = @_; my $class = ref $proto || $proto; check_object_param( $args{'spec'}, 'spec', 'Lire::Config::ConfigSpec' ); check_param( $args{'filename'}, 'filename' ); my $self = bless { 'spec' => $args{'spec'}, 'filename' => $args{'filename'}, 'global' => new Lire::Config::Dictionary( 'spec' => $args{'spec'} ), }, $class; return $self; } =pod =head2 filename( [$new_filename] ) Returns (and optionally changes) the filename where this configuration file should be stored. =cut sub filename { my ( $self, $filename ) = @_; if ( @_ == 2 ) { check_param( $filename, 'filename' ); $self->{'filename'} = $filename; } return $self->{'filename'}; } =pod =head2 spec() Returns the Lire::Config::TypeSpec object to which this configuration file adheres. =cut sub spec { $_[0]{'spec'}; } =pod =head2 global( [ $config] ) Returns or modify the 'global' configuration part of the file. This is an instance Lire::Config::Compound object. =cut sub global { my ( $self, $config ) = @_; if ( @_ == 2 ) { if ( defined $config ) { croak "'config' parameter isn't an Lire::Config::Dictionary instance: $config" unless UNIVERSAL::isa( $config, "Lire::Config::Dictionary" ); } $self->{'global'} = $config; } return $self->{'global'}; } sub save_global { my ( $self, $fh, $indent, $xmlns ) = @_; $indent ||= 0; $xmlns ||= ''; print $fh ' 'x$indent, "<${xmlns}global>\n"; $self->global()->save_value( $fh, $indent, $xmlns ); print $fh ' 'x$indent, "\n"; return; } =pod =head2 save() Saves this ConfigConfigFile object back to the filename from which it was loaded. =cut sub save { my $self = $_[0]; open my $fh, "> $self->{'filename'}" or die "open '$self->{'filename'}' for writing failed: $!\n"; $self->save_xml( $fh ); close $fh; return; } =pod =head2 revert() Reads back the configuration from the file. =cut sub revert { my $self = $_[0]; my $parser = new Lire::Config::Parser( 'spec' => $self->{'spec'} ); my $new_self = $parser->load_config_file( $self->{'filename'} ); %$self = %$new_self; return; } sub save_xml { my $self = shift; my $fh = $_[0]; set_fh_encoding( $fh, 'UTF-8' ); print $fh join("\n", '', '', ']>', '', ''); $self->save_global($fh, 1); print $fh "\n"; return; } =pod =head2 as_value() Returns this configuration file as an hash reference. Delegates to the global configuration object contained in the file. =cut sub as_value { shift->{'global'}->as_value( @_ ) }; =pod =head2 get( $name ) Returns the configuration parameter $name from this configuration file. Delegates to the global configuration object contained in the file. =cut sub get { shift->{'global'}->get( @_ ) }; =pod =head2 is_set( $name ) Checks that a configuration parameter is set in this file. Delegates to the global configuration object contained in the file. =cut sub is_set { shift->{'global'}->is_set( @_ ) }; =pod =head2 set( $param ) Sets a configuration variable in the file. Delegates to the global configuration object contained in the file. =cut sub set { shift->{'global'}->set( @_ ) }; 1; # whine, whine __END__ =pod =head1 SEE ALSO Lire::Config::Dictionary(3pm) =head1 AUTHORS Wessel Dankers Francis J. Lacoste Wolfgang Sourdeau =head1 VERSION $Id: ConfigFile.pm,v 1.9 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/RecordSpec.pm0000644000175000017500000000056210460672575015413 00000000000000package Lire::Config::RecordSpec; use strict; use base qw/Lire::Config::CompoundSpec/; use Lire::Config::Dictionary; =pod =head1 NAME Lire::Config::RecordSpec - Specification for a record-like type. =head1 DESCRIPTION Lire::Config::TypeSpec object which specifies a record-like parameter. =cut sub instance_class { return 'Lire::Config::Dictionary'; } 1; lire-2.1.1/all/lib/Lire/Config/ListSpec.pm0000644000175000017500000000236110460673256015104 00000000000000package Lire::Config::ListSpec; use strict; =pod =head1 Lire::Config::ListSpec Describes a type of configuration variables that represent a list of other types. =cut use base qw/Lire::Config::CompoundSpec/; sub instance_class { return "Lire::Config::List"; } 1; __END__ =pod =head1 VERSION $Id: ListSpec.pm,v 1.4 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/XMLSpecListSpec.pm0000644000175000017500000001622410460673257016304 00000000000000package Lire::Config::XMLSpecListSpec; use strict; use base qw/Lire::Config::ListSpec/; use Lire::Config::StringSpec; use Lire::Config::ObjectSpec; use Lire::Config::ListSpec; use Lire::Config::ChartSpec; use Lire::ReportSpec; use Lire::FilterSpec; use Lire::Utils qw/check_param/; use Locale::TextDomain 'lire'; use Carp; our $NAME_RE = qr/^([\w_-]+):([\w_.-]+)$/; =pod =head1 NAME Lire::Config::XMLSpecListSpec - List of XML specifications. =head1 DESCRIPTION This Lire::Config::TypeSpec defines a special kind of ListSpec. It overrides the has_component(), get(), component_names() and components() methods so that every XML report specifications or filter specifications are available. The specifications are created dynamically at runtime. =head2 new( 'name' => $name, 'type' => 'filters'|'reports ) Creates a new Lire::Config::XMLSpecListSpec object which will contains a list of report or filter specifications configuration. The type parameter is used to select whether Lire::ReportSpec or Lire::FilterSpec will be creatd. =cut sub new { my $self = shift->SUPER::new( @_ ); my $type = { @_ }->{'type'}; check_param( $type, 'type', qr/^filters|reports$/, "'type' parameter should be either filters or reports" ); $self->{'_type'} = $type; $self->{'_module'} = ( $type eq 'reports' ? 'Lire::ReportSpec' : 'Lire::FilterSpec' ); $self->{'_cache'} = {}; return $self; } =pod =head2 type() Returns the type of specification contained by this object. =cut sub type { return $_[0]{'_type'}; } =pod =head2 has_component( $name ) This spec will return true when $name is of the form I:I and there is an available I specification defined in I. It returns false otherwise. =cut sub has_component { my ( $self, $name ) = @_; check_param( $name, 'name' ); my ( $super, $type ) = $name =~ /$NAME_RE/; return 0 unless defined $super && defined $type; return Lire::DlfSchema->has_superservice( $super ) && $self->{'_module'}->has_spec( $super, $type ); } =pod =head2 component_names() Returns an array containing the configuration name of all available specifications. =cut sub component_names { my $self = $_[0]; my @specs = (); foreach my $super ( Lire::DlfSchema->superservices() ) { foreach my $type ( @{$self->{'_module'}->list_specs( $super )} ) { push @specs, "$super:$type"; } } return @specs; } =pod =head2 get( $name ) Returns an Lire::Config::ObjectSpec specification for the component named $name. The ObjectSpec will instantiate a Lire::ReportSpec or Lire::FilterSpec of the appropriate type. =cut sub get { my ( $self, $name ) = @_; croak "no component named '$name'" unless $self->has_component( $name ); return $self->{'_cache'}{$name} if exists $self->{'_cache'}{$name}; my ( $super, $type ) = $name =~ /$NAME_RE/; my $xml_spec = $self->{'_module'}->load( $super, $type ); my $spec = new Lire::Config::ObjectSpec( 'name' => $name, 'i18n_domain' => "lire-$super", 'class' => $self->{'_module'}, 'summary' => $xml_spec->title(), 'description' => $xml_spec->description(), 'label' => 'id', ); $spec->add( new Lire::Config::StringSpec( 'name' => 'id', 'valid-re' => '^[\w.:-]+$', 'summary' => N__( 'Identifier' ), 'description' => '' . join( "", N__( 'Identifier that uniquely identifies this specification among the report configuration. When two reports are merged, specifications with the same identifier are merged together.' ) ) . "" ) ); my $title = new Lire::Config::StringSpec( 'name' => 'title', 'required' => 0, 'summary' => N__( 'Custom Title' ), 'description' => '' . join( "", N__( 'If this parameter is set, its value will be used instead of the display title specified in the specification. This string will interpolate $name_ref with the parameter\'s value when the report is generated.' ) ) . '' ); $title->default( $title->instance( 'value' => $xml_spec->display_title())); $spec->add( $title ); foreach my $name ( $xml_spec->param_names() ) { $spec->add( $xml_spec->param( $name )->as_type_spec() ); } $self->_set_charts_spec( $xml_spec, $spec ); return $self->{'_cache'}{$name} = $spec; } sub _set_charts_spec { my ( $self, $xml_spec, $spec ) = @_; return unless $xml_spec->isa( 'Lire::ReportSpec' ); my $charts = new Lire::Config::ListSpec( 'name' => 'charts', 'summary' => N__( 'Charts' ), 'description' => '' . join ( "", N__( "Parameters for the charts that should be generated from this subreport's data" ) ) . "" ); $spec->add( $charts ); $charts->add( new Lire::Config::ChartSpec( 'name' => 'chart', 'summary' => N__( 'Chart' ), 'description' => '' . join( "", N__( "Parameters for a chart that should be generated from this subreport's data." ) ) . "" ) ); my $default = $charts->instance(); foreach my $cfg ( @{$xml_spec->chart_configs()} ) { my $default_chart = $cfg->clone(); $default_chart->{'spec'} = $charts->get( 'chart' ); $default->append( $default_chart ); } $charts->default( $default ); return; } =pod =head2 components() Returns an array containing all the Lire::Config::ObjectSpec defining the available specifications. =cut sub components { my $self = $_[0]; my @comps = (); foreach my $name ( $self->component_names() ) { push @comps, $self->get( $name ); } return @comps; } 1; __END__ =pod =head2 SEE ALSO Lire::Config::ReportSectionSpec(3pm), Lire::Config::ReportSpec(3pm), Lire::ReportSpec(3pm), Lire::FilterSpec(3pm). =head1 VERSION $Id: XMLSpecListSpec.pm,v 1.8 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/TypeSpec.pm0000644000175000017500000001763610460673257015126 00000000000000package Lire::Config::TypeSpec; use strict; use Carp; use Lire::DataTypes qw/ check_xml_name check_nmtoken /; use Lire::I18N qw/ dgettext dgettext_para /; use Lire::ReportParser::AsciiDocBookFormatter qw/ dbk2txt /; use Lire::Utils qw/ check_param check_object_param /; BEGIN { no strict 'refs'; foreach my $pkg (qw/Scalar Compound Object List Config String File Command Executable Directory Boolean Integer Select Option DlfAnalyser DlfConverter DlfSchema DlfStream DlfStreams Record Reference Report ReportSection Plugin XMLSpecList Chart ChartType OutputFormat / ) { eval "use Lire\::Config\::${pkg}Spec"; die if $@; } } =pod =head1 NAME Lire::Config::TypeSpec - Base class for object which specifies configuration types. =head1 DESCRIPTION Abstract superclass for the other type classes. Implements basic methods but croaks when those are invoked. =head2 new( 'name' => $name ) The constructor takes one mandatory argument which is the parameter's name. =cut sub new { my ( $class, %args ) = @_; check_param ( $args{'name'}, 'name', \&check_xml_name, "name should only contain digits, numbers or '.', '-' or '_'" ); my $self = bless { 'name' => $args{'name'}, 'section' => undef, 'summary' => $args{'summary'}, 'description' => undef, 'i18n_domain' => $args{'i18n_domain'} || 'lire', '_required' => 1, '_obsolete' => $args{'obsolete'} || 0, '_default' => undef, }, $class; $self->required( $args{'required'} ) if defined $args{'required'}; $self->section($args{'section'}); $self->description( $args{'description'} ) if defined $args{'description'}; return $self; } =pod =head2 name() Returns the parameter's name. =cut sub name { return $_[0]{'name'}; } =pod =head2 has_section() Returns if this parameter is interesting for the given section. =cut sub has_section { my $self = shift; foreach(@_) { if(defined) { s/^\s+|\s+$//g; return lc eq $self->section(); } else { return !defined $self->section(); } } return; } =pod =head2 section() Returns a the section of this parameter. If an argument is passed, it is used to change the section. It's ok to pass undef as a parameter (treated as "not a member of any section"). =cut sub section { my $self = shift; foreach(@_) { if(defined) { s/^\s+|\s+$//g; $self->{'section'} = lc; } else { $self->{'section'} = undef; } } return $self->{'section'}; } =pod =head2 has_default() Returns whether this TypeSpec has a default configuration value specified. =cut sub has_default { return defined $_[0]{'_default'}; } =pod =head2 default( [ $new_default ] ) Returns the Lire::Config::Value object which will be used as a template. It returns undef if there is no default defined. The $new_default parameter can be used to change the current default. This value should be a Lire::Config::Value that was instantiated by this specification. =cut sub default { my ( $self, $new_default ) = @_; if ( @_ == 2 ) { if ( defined $new_default ) { check_object_param( $new_default, 'new_default', 'Lire::Config::Value' ); croak "default value doesn't come from this specification" unless $self->is_instance( $new_default ); } $self->{'_default'} = $new_default; } return $self->{'_default'}; } =pod =head2 required( [ $is_required ] ) Returns whether this configuration parameter is required. Container of this parameter will use this result in their is_valid() implementation. Values that are invalid but not required will not make the is_valid() test fails. By default, all parameters are required. =cut sub required { my $self = $_[0]; $self->{'_required'} = $_[1] ? 1 : 0 if ( @_ == 2 ); return $self->{'_required'}; } =pod =head2 obsolete( [ $is_obsolete ] ) Returns (and optionally changes) the obsolete flag for this parameter. =cut sub obsolete { my $self = $_[0]; $self->{'_obsolete'} = $_[1] ? 1 : 0 if ( @_ == 2 ); return $self->{'_obsolete'}; } =pod =head2 summary( [$summary] ) Returns this parameter summary description. It can also be used to change the parameter's summary. =cut sub summary { my $self = $_[0]; if ( @_ == 2 ) { $self->{'summary'} = $_[1]; } return $self->{'name'} unless defined $self->{'summary'}; my $summary = $self->{'summary'}; $summary =~ s/(^ +| +$)//gm; $summary =~ s/\n/ /g; return dgettext( $self->{'i18n_domain'}, $summary ); } =pod =head2 description( [$description] ) Returns this parameter's description. This is a DocBook string. It can also be used to change the parameter's description. =cut sub description { my $self = $_[0]; if (@_ == 2) { croak "'description' parameter should be a DocBook string" if defined $_[1] && $_[1] !~ /^\s*<[\w.-]+>/; $self->{'description'} = $_[1]; } my $description = $self->{'description'}; return undef unless defined $description; $description =~ s/(^ +| +$)//gm; $description =~ s/\n/ /gm; return dgettext_para( $self->{'i18n_domain'}, $description ); } =pod =head2 text_description() Returns the specification's description formatted in plain text, one line per paragraph. =cut sub text_description { my $self = $_[0]; my $description = $self->description(); return undef unless defined $description; my $text = dbk2txt( $description, 32_766 ); $text =~ s/^ +//gm; $text =~ s/ +$//gm; chomp $text while ( substr( $text, -1, 1 ) eq "\n" ); return $text; } =pod =head2 instance( %params ) This method is a factory type function which returns a new Lire::Config::Value object of the correct type. If the specification has a default value, the returned instance will be a clone of that value, otherwise an unitialized value will be returned. %params can contains any parameters accepted by the Lire::Config::Value constructor. =cut sub instance { my $self = shift; if ( $self->{'_default'} ) { return $self->{'_default'}->new( @_ ); } else { return $self->instance_class()->new( @_, 'spec' => $self ); } } =pod =head2 is_instance( $value_object ) Returns true if $value_object is a valid instance of this parameter. =cut sub is_instance { my ( $self, $instance ) = @_; check_object_param( $instance, 'instance', 'Lire::Config::Value' ); return $instance->spec() eq $self; } sub instance_class { croak( "instance_class_() method not implemented in ", ref $_[0] ); } 1; __END__ =pod =head1 VERSION $Id: TypeSpec.pm,v 1.25 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ReportSpec.pm0000644000175000017500000000575210460673256015453 00000000000000package Lire::Config::ReportSpec; use strict; use base qw/Lire::Config::ObjectSpec/; use Lire::Config::StringSpec; use Lire::Config::ListSpec; use Lire::Config::ReportSectionSpec; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::Config::ReportSpec - Defines a report configuration. =head1 DESCRIPTION This Lire::Config::TypeSpec is a CompoundSpec which defines a report that can be generated. =head2 new( 'name' => $name ) A report configuration object holds an id which appears in display list, an optional title and a list of sections. =cut sub new { my $self = shift->SUPER::new( @_, 'label' => 'id', 'class' => 'Lire::ReportConfig' ); $self->add( new Lire::Config::StringSpec( 'name' => 'id', 'summary' => N__( "Report's identifier" ), 'description' => '' . join( "", N__( 'This identifier can be used to refer to this report configuration.' ) ) . '' ) ); $self->add( new Lire::Config::StringSpec( 'name' => 'title', 'summary' => N__( "Report's title" ), 'description' => '' . join( "", N__( 'A title that will appears in the report.' ) ) . '' ) ); my $sections = new Lire::Config::ListSpec( 'name' => 'sections', 'summary' => N__( "Report's sections" ), 'description' => '' . join( "", N__( 'List of sections defined in the report.' ) ) . '' ); $sections->add( new Lire::Config::ReportSectionSpec( 'name' => 'section', 'summary' => N__( 'Section definition' ), 'description' => '' . join( "", N__( 'Defines a report section.' ) ) . '' ) ); $self->add( $sections ); return $self; } 1; __END__ =pod =head2 SEE ALSO Lire::Config::XMLSpecListSpec(3pm), Lire::Config::ReportSectionSpec(3pm), Lire::ReportConfig(3pm) =head1 VERSION $Id: ReportSpec.pm,v 1.3 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/OutputFormatSpec.pm0000644000175000017500000000271410460673256016644 00000000000000package Lire::Config::OutputFormatSpec; use strict; use Lire::PluginManager; =pod =head1 NAME Lire::Config::OutputFormatSpec - PluginSpec for OutputFormat. =head1 DESCRIPTION This is a Lire::Config::PluginSpec object that can be used to select any available Lire::OutputFormatSpec. =cut use base qw/Lire::Config::BasePluginSpec/; sub plugin_type { return "output_format"; } sub options { my $self = $_[0]; return grep { ! Lire::PluginManager->get_plugin( 'output_format', $_->name() )->missing_requirements() } $self->SUPER::options(); } 1; __END__ =pod =head1 VERSION $Id: OutputFormatSpec.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/OptionSpec.pm0000644000175000017500000000250510460673256015441 00000000000000package Lire::Config::OptionSpec; =head1 Lire::Config::OptionSpec Type that represents a specific choice =cut use base qw/Lire::Config::TypeSpec/; use Carp; =pod =head2 is_option( $value ) Returns true if $value is equals to this option name. =cut sub is_option { my ( $self, $value ) = @_; return lc $self->{'name'} eq lc $value; } 1; __END__ =pod =head1 VERSION $Id: OptionSpec.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/PluginSpec.pm0000644000175000017500000000474010460673256015432 00000000000000package Lire::Config::PluginSpec; use strict; =pod =head1 NAME Lire::Config::PluginSpec - SelectSpec with variable properties. =head1 DESCRIPTION Lire::Config::TypeSpec that represents a configuration variable which defines additional properties based on the value which is currently selected. This can be used for extensible type like DlfConverter or OutputFormat. =cut use base qw/Lire::Config::SelectSpec/; use Lire::Config::Plugin; use Lire::Config::RecordSpec; use Carp; =pod =head2 new() Create a Lire::Config::SectionSpec object. =cut sub new { my $self = shift->SUPER::new( @_ ); $self->{'_no_properties_spec'} = new Lire::Config::RecordSpec( 'name' => $self->name() . "_no_properties" ); return $self; } sub instance_class { return 'Lire::Config::Plugin'; } =pod =head2 get_properties_spec( $option ) Returns the TypeSpec that specifies the properties of the $option. This method will return an empty RecordSpec when the plugin didn't define any properties. One can also use the has_properties() method to check if the Plugin defined configuration properties. =cut sub get_properties_spec { my ( $self, $option ) = @_; return $self->{'_no_properties_spec'} unless defined $option; my $name = $self->normalize( $option ); croak "no option '$option' in this specification" unless defined $name; $name .= '_properties'; my $spec = Lire::Config->config_spec(); return $spec->get( $name ) if $spec->has_component( $name ); return $self->{'_no_properties_spec'}; } 1; __END__ =pod =head1 VERSION $Id: PluginSpec.pm,v 1.6 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/CompoundSpec.pm0000644000175000017500000000656310460673256015765 00000000000000package Lire::Config::CompoundSpec; use strict; =pod =head1 Lire::Config::CompoundSpec Describes an abstract type for configuration variables that can contain subtypes. =cut use base qw/ Lire::Config::TypeSpec /; use Lire::Utils qw/ check_param check_object_param /; use Lire::DataTypes qw/check_xml_name/; use Lire::Config::Value; use Carp; sub new { my $class = shift; my %args = @_; my $self = $class->SUPER::new( %args ); $self->{'label'} = $args{'label'} if exists ( $args{'label'} ); $self->{'components'} = []; $self->{'index'} = {}; return $self; } =pod =head2 has_component( $name ) Returns true if this type has a component named $name. =cut sub has_component { my ( $self, $name ) = @_; check_param( $name, 'name' ); return exists $self->{'index'}{$name}; } =pod =head2 component_names() Returns the name of all components defined in this spec. =cut sub component_names { return map { $_->name() } $_[0]->components(); } =pod =head2 components() Returns an array containing the subtypes contained in this compound type. =cut sub components { return @{$_[0]{'components'}}; } =pod =head2 label_component() Returns the component name that holds the label for identifying instances in GUI. =cut sub label_component { my $self = $_[0]; return undef unless defined $self->{'label'}; croak "'$self->{'label'}' component does not exist" unless $self->has_component( $self->{'label'} ); return $self->{'label'}; } =pod =head2 add( $type ) This method adds $type as a component of this type. =cut sub add { my ($self, $type) = @_; check_object_param( $type, 'type', 'Lire::Config::TypeSpec' ); my $type_name = $type->name(); croak( "'" . $self->name() . "' already contains a component named '$type_name'" ) if exists $self->{'index'}{ $type_name }; $self->{'index'}{$type_name} = push ( @{$self->{'components'}}, $type ) - 1; return; } =pod =head2 get( $name ) The get() method returns the component of this type with the requested name. =cut sub get { my ( $self, $name ) = @_; check_param( $name, 'name', \&check_xml_name, "invalid 'name' parameter" ); croak "no component named '$name' in type $self->{'name'}" unless exists $self->{'index'}{$name}; my $idx = $self->{'index'}{$name}; return $self->{'components'}[$idx]; } 1; __END__ =pod =head1 VERSION $Id: CompoundSpec.pm,v 1.9 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wessel Dankers Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Config/ChartSpec.pm0000644000175000017500000000750710460673256015241 00000000000000package Lire::Config::ChartSpec; use strict; use base qw/Lire::Config::CompoundSpec/; use Lire::Config::StringSpec; use Lire::Config::ChartTypeSpec; use Lire::Report::ChartConfig; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::Config::ChartSpec - Defines a chart to generate. =head1 DESCRIPTION This Lire::Config::TypeSpec is a CompoundSpec which can be used to configure a chart to generate from a Subreport. =head2 new() Create a Lire::Config::ChartSpec object. =cut sub new { my $self = shift->SUPER::new( @_, 'label' => 'name' ); $self->add( new Lire::Config::StringSpec( 'name' => 'name', 'required' => '0', 'summary' => "Chart's basename", 'description' => '' . join( "", N__( "The basename of the chart. An extension will be appended based on the chart's format. If this attribute isn't set, the Subreport'id will be used." ) ) . "" ) ); $self->add( new Lire::Config::StringSpec( 'name' => 'title', 'required' => 0, 'summary' => "Title", 'description' => '' . join( "", N__( "The title that will appear on the chart." ) ) . "" ) ); $self->add( new Lire::Config::ChartTypeSpec( 'name' => 'type', 'summary' => "Type", 'description' => '' . join( "", N__( "The type of charts to generate. Chart types are plugins." ) ) . "" ) ); $self->add( new Lire::Config::ReferenceSpec( 'name' => 'case_var', 'index' => 'categorical_variables', 'summary' => "Case", 'description' => '' . join( "", N__( "The categorical variable that will be used to select the case that will make the chart's data." ) ) . "" ) ); $self->add( new Lire::Config::StringSpec( 'name' => 'xlabel', 'required' => 0, 'summary' => "X Axis Label", 'description' => '' . join( "", N__( "A title that will appear under the X axis." ) ) . "" ) ); $self->add( new Lire::Config::StringSpec( 'name' => 'ylabel', 'required' => 0, 'summary' => "Y Axis Label", 'description' => '' . join( "", N__( "A title that will appear along the Y axis." ) ) . "" ) ); return $self; } sub instance_class { return "Lire::Report::ChartConfig"; } 1; __END__ =pod =head2 SEE ALSO Lire::Config::ChartTypeSpec(3pm), Lire::ChartType(3pm) =head1 VERSION $Id: ChartSpec.pm,v 1.6 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Param.pm0000644000175000017500000001063210460673255013210 00000000000000package Lire::Param; use strict; use Lire::Config::TypeSpec; use Lire::DataTypes qw/ check_xml_name check_type /; use Lire::Utils qw/ check_param /; use Lire::I18N qw/ dgettext_para /; =pod =head1 NAME Lire::Param - Object which represents a parameter in a XML specification. =head1 DESCRIPTION Lire::Param are objects which represent parameters in an XML specification. The object is used to represent the parameter's specification as well as its current value. =head2 new( 'name' => $name, 'type' => $type, [ 'default' => $default ] ) Creates a new Lire::Param object. =cut sub new { my ( $class, %params ) = @_; check_param( $params{'name'}, 'name', \&check_xml_name ); check_param( $params{'type'}, 'type', \&check_type ); my $self = bless { 'name' => $params{'name'}, 'type' => $params{'type'}, 'i18n_domain' => $params{'i18n_domain'} || 'lire', 'description' => $params{'description'}, }, $class; $self->default( $params{'default'} ) if defined $params{'default'}; $self->value( $params{'value'} ) if defined $params{'value'}; return $self; } =pod =head2 name() Returns the name of this parameter. =cut sub name { return $_[0]->{'name'}; } =pod =head2 type() Returns this parameter's type. =cut sub type { return $_[0]->{'type'}; } =pod =head2 value( [ $new_value ] ) Returns (and optionnally modifies) the current value for this parameter. If no value was set, but a default is available, the default value will be returned. =cut sub value { my ($self, $value ) = @_; if ( @_ == 2 ) { if ( defined $value ) { check_param( $value, 'value', $Lire::DataTypes::VALIDATORS{$self->{'type'}} ); $self->{'value'} = $value; } else { $self->{'value'} = undef; } } # Check for default if ( defined $self->{'value'}) { return $self->{'value'}; } else { return $self->default(); } } =pod =head2 default( [ $new_default ] ) Returns (and optionnally changes) the parameter's default value. =cut sub default { my ( $self, $default ) = @_; if ( defined $default ) { check_param( $default, 'default', $Lire::DataTypes::VALIDATORS{$self->{'type'}} ); $self->{'default'} = $default; } return $self->{'default'}; } =pod =head2 description( [ $new_description ] ) Returns (and optionnally changes) the current parameter's description. =cut sub description { my ( $self, $desc ) = @_; if ( @_ == 2 ) { $self->{'description'} = $desc; } return dgettext_para( $self->{'i18n_domain'}, $self->{'description'} ); } =pod =head2 as_type_spec() Returns a Lire::Config::TypeSpec object which adequately represents the current parameter. =cut my %types2spec = ( 'int' => 'Lire::Config::IntegerSpec', 'bool' => 'Lire::Config::BooleanSpec', 'filename', => 'Lire::Config::FileSpec' ); sub as_type_spec { my $self = $_[0]; my $type = $types2spec{$self->{'type'}} || 'Lire::Config::StringSpec'; my $spec = $type->new( 'name' => $self->{'name'}, 'i18n_domain' => $self->{'i18n_domain'}, 'description' => $self->{'description'} ); $spec->default( $spec->instance( 'value' => $self->{'default'} ) ) if defined $self->{'default'}; return $spec; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Config::TypeSpec(3pm), Lire::XMLSpecContainer(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: Param.pm,v 1.13 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001,2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/ReportJob.pm0000644000175000017500000000713110460673255014056 00000000000000package Lire::ReportJob; use strict; use Carp; use Lire::DlfSchema; use Lire::Utils qw/ check_param check_object_param /; =pod =head1 NAME Lire::ReportJob - Object used to configure periodical report generation =head1 SYNOPSIS use Lire::ReportJob; use Lire::ReportSchedule; my $store = Lire::DlfStore->open( 'aStore' ); my $job = new Lire::ReportJob( "webServer" ); my $cfg = $store->get_report_config( 'my_report' ); $job->add_schedule( new Lire::ReportSchedule( 'daily', $cfg ); $job->run( $store, 'daily' ); =head1 DESCRIPTION The Lire::ReportJob object is used to configure and execute report generation jobs. These objects are usually configured in a store through the lire(1) command. =head2 new( $name, ); Create a new Lire::ReportJob(). The constructor takes one parameter which is an identifier. =cut sub new { my ( $class, $name ) = @_; check_param( $name, 'name', qr/^[\w-]+$/ ); my $self = bless { '_name' => $name, '_schedules' => [], }, $class; return $self; } =pod =head2 name() Returns the name of this ReportJob. =cut sub name { $_[0]{'_name'} }; =pod =head2 add_schedule( $schedule, ... ) Adds one or more Lire::ReportSchedule to the ReportJob objects. =cut sub add_schedule { my ( $self, @schedules ) = @_; croak "missing one or more 'schedule' parameters" unless @schedules; foreach my $s ( @schedules ) { check_object_param( $s, 'schedule', 'Lire::ReportSchedule' ); push @{$self->{'_schedules'}}, $s; } return; } =pod =head2 schedules() Returns the Lire::ReportSchedule related to this object. =cut sub schedules { return @{$_[0]{'_schedules'}}; } =pod =head2 run( $store, $period, [$time] ) Executes all the configured generation with a period of 'period' using the $store DlfStore. Once the method returns, XML report will have been generated in the DlfStore and OutputJob associated with the ScheduleJob will have been sent. The $time parameter will be used to determine the time window covered by period. It defaults to the current time. =cut sub run { my ( $self, $store, $period, $time ) = @_; $time ||= time(); foreach my $sched ( $self->schedules() ) { next unless $sched->period() eq $period; $sched->run( $store, $self, $time ); } return; } sub new_from_config { my ( $pkg, $dict ) = @_; $dict = $dict->Lire::Config::Dictionary::as_value(); my $job = new Lire::ReportJob( $dict->{'name'} ); $job->add_schedule( @{$dict->{'schedules'}} ) if @{$dict->{'schedules'}}; return $job; } 1; __END__ =pod =head1 SEE ALSO Lire::DlfStore(3pm) Lire::ImportJob(3pm) Lire::ReportSchedule(3pm) lire(1) Lire::OutputJob(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: ReportJob.pm,v 1.9 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/DlfStore.pm0000644000175000017500000005425611677604543013711 00000000000000package Lire::DlfStore; use strict; use Lire::DlfStream; use Lire::DlfAnalyserProcess; use Lire::DlfQuery; use Lire::SQLExt::Registry; use Lire::WeekCalculator; use Lire::Config::Index; use Lire::Config::ReportConfigIndex; use Lire::ReportConfig; use Lire::Utils qw/check_param check_object_param min max unique/; use File::Path qw/mkpath/; use File::Basename qw/dirname basename/; use POSIX qw/strftime/; use Errno; use Fcntl; use DBI; use Carp; =pod =head1 NAME Lire::DlfStore - Interface to a DLF store =head1 SYNOPSIS use Lire::DlfStore; my $store = Lire::DlfStore->open( "mystore", 1 ); my $avail_streams = $store->dlf_streams; =head1 DESCRIPTION =head2 open( $store_path, [ $create ] ); Opens a Lire::DlfStore residing in the directory pointed by $store_path and returns a Lire::DlfStore instance that can be used to access its content. If the store $store_path wasn't created, the method will die unless the $create parameter was set to true. If the store is locked by another process, the method will also die. Trying to open the same store twice from the same process will fail. =cut sub open { my ( $pkg, $store_path, $create ) = @_; check_param( $store_path, 'store_path' ); my $self = bless { '_store_path' => $store_path, '_dbh' => undef, '_config' => undef, }, $pkg; if ( ! -d $store_path ) { croak "DlfStore '$store_path' doesn't exist" unless $create; $self->_create_store(); } elsif ( !( -f $self->{'_store_path'} . "/dlf.db" && -f $self->{'_store_path'} . "/config.xml" ) ) { croak "Invalid DlfStore: '$store_path'" unless $create; } $self->_load_config_file(); $self->{'_dbh'} = DBI->connect( "dbi:SQLite:dbname=" . $self->{'_store_path'} . "/dlf.db", "", "", { 'RaiseError' => 1, 'AutoCommit' => 0, } ); Lire::SQLExt::Registry->register_functions( $self->{'_dbh'} ); Lire::SQLExt::Registry->register_aggregates( $self->{'_dbh'} ); my $locked_by = $self->_lock(); die "DlfStore '$store_path' is locked by process $locked_by\n" unless $locked_by == $$; $self->_migrate_report_jobs(); return $self; } sub _load_config_file { my $self = $_[0]; my $config_file = "$self->{'_store_path'}/config.xml"; if ( -f $config_file ) { my $parser = Lire::Config::Parser->new( 'spec' => Lire::Config->config_spec() ); $self->{'_config'} = $parser->load_config_file( $config_file ); } else { $self->{'_config'} = new Lire::Config::ConfigFile( 'spec' => Lire::Config->config_spec(), 'filename' => $config_file ); } Lire::Config::Index->set_index( 'store_report_configurations', new Lire::Config::ReportConfigIndex( $self->{'_config'}->get( 'reports' ) ) ); return; } sub _migrate_report_jobs { my $self = $_[0]; foreach my $job ( $self->{'_config'}->get( 'report_jobs' )->elements() ) { $self->_migrate_report_job( $job ) if $job->is_set( 'superservice' ); } return; } sub _migrate_report_job { my ( $self, $job ) = @_; my $super = $job->get( 'superservice' )->get(); foreach my $sched ( $job->get( 'schedules' )->elements() ) { my $cfgref = $self->_find_config( $super, $sched->get( 'report_cfg' )->get() ); $sched->get( 'report_config' )->set( $cfgref ); } return; } sub _find_config { my ( $self, $super, $file ) = @_; my $id = basename( $file ); return $id if $self->has_report_config( $id ); my $cfg = new_from_file Lire::ReportConfig( $super, $file )->as_config_value( $id ); $cfg->{'spec'} = $self->{'_config'}->spec()->get( 'reports' )->get( 'report_cfg' ); $self->{'_config'}->get( 'reports' )->append( $cfg ); return $id; } =pod =head2 close() Calls this method to release the lock held by the current process on the store. If you don't call it, it will be called automatically when the store reference goes out of scope, but you better not rely on this to close your stores. =cut sub close { my ($self, $in_destroy) = @_; $self->_unlock(); # DESTROY calls close() another time if ( $self->{'_dbh'} ) { $self->{'_dbh'}->commit(); # Clear any cached results from prepare_cached() before disconnecting, # to avoid infamous 'closing dbh with active statement handle' warning. my $CachedKids_hashref = $self->{'_dbh'}->{CachedKids}; %$CachedKids_hashref = () if $CachedKids_hashref; $self->{'_dbh'}->disconnect(); delete $self->{'_dbh'}; $self->{'_config'}->save() unless $in_destroy; Lire::Config::Index->set_index( 'store_report_configurations', undef ); } } =pod =head2 is_closed() Returns true if this DlfStore was closed and cannot be used anymore. =cut sub is_closed { return ! exists $_[0]->{'_dbh'}; } =pod =head2 path Returns the path to the store. This is the argument used to create the store. =cut sub path { return $_[0]{'_store_path'}; } =pod =head2 config Returns the configuration of the store instantiated as a Lire::Config::ConfigFile. =cut sub config { return $_[0]{'_config'}; } =pod =head2 import_jobs() Returns as an array ref the list of ImportJob currently configured in the DlfStore =cut sub import_jobs { my $self = $_[0]; return $self->{'_config'}->get( 'import_jobs' )->as_value(); } =pod =head2 report_jobs() Returns as an array ref the list of ReportJob currently configured in the DlfStore =cut sub report_jobs { my $self = $_[0]; return $self->{'_config'}->get( 'report_jobs' )->as_value(); } =pod =head2 has_report_config( $name ) Returns true if there is a report configuration named $name in this DlfStore. =cut sub has_report_config { my ( $self, $name ) = @_; check_param( $name, 'name' ); foreach my $cfg ( $self->{'_config'}->get( 'reports' )->elements() ) { return 1 if $cfg->get( 'id' )->get() eq $name; } return 0; } =pod =head2 report_configurations() Returns as an array ref the list of ReporConfig currently configured in the DlfStore =cut sub report_configurations { my $self = $_[0]; return $self->{'_config'}->get( 'reports' )->as_value(); } =pod =head2 get_report_config( $name ) Returns the Lire::ReportConfig object named $name. Throws an exception if it doesn' exists. =cut sub get_report_config { my ( $self, $name ) = @_; check_param( $name, 'name' ); croak "there is no report configuration named '$name'" unless $self->has_report_config( $name ); foreach my $cfg ( $self->{'_config'}->get( 'reports' )->elements() ) { return $cfg->as_value() if $cfg->get( 'id' )->get() eq $name; } } #------------------------------------------------------------------------ # Method _create_store( ) # # Creates the DlfStore structure. sub _create_store { my $self = $_[0]; mkdir $self->{'_store_path'}, 0770 or croak "can't create DLF store '$self->{'_store_path'}: $!"; return; } #------------------------------------------------------------------------ # Method _lock() # # Acquire a lock on the store. This is done automatically from open() # It tries three time to acquired the lock before returning. It # returns the process id of the owner of the lock. To check if the # lock was acquired the called must check that this is equals to $$. sub _lock { my $self = $_[0]; # Do not try to acquired another lock. return if $self->{'_lock_file'}; my $lock_file = $self->{'_store_path'} . "/lock"; my $lock_fh; my $max_try = 3; for ( my $try =1; $try <= $max_try; $try++ ) { if ( sysopen( $lock_fh, $lock_file, O_EXCL|O_CREAT|O_RDWR) ) { print $lock_fh $$, "\n"; CORE::close $lock_fh; $self->{'_lock_file'} = $lock_file; return $$; } if ( CORE::open $lock_fh, $lock_file ) { my $lock_pid = <$lock_fh>; chomp $lock_pid; if (kill( 0, $lock_pid) || $!{'EPERM'} ) { return $lock_pid if $try == $max_try; sleep 2; } else { # Stale lock unlink( $lock_file ) == 1 or croak "can't remove stale lock file '$lock_file': $!"; } } } die "ASSERTION FAILED: unreachable code"; } #------------------------------------------------------------------------ # Method _unlock() # # Release the lock previously acquired by _lock() method. sub _unlock { my $self = $_[0]; return unless $self->{'_lock_file'}; unlink $self->{'_lock_file'}; } sub DESTROY { my $self = $_[0]; $self->close( 'in_destroy' ); } =pod =head1 DLF STREAMS RELATED METHOD A DlfStore can contains multiple Dlf Stream. Dlf Stream is data conforming to a DLF schema. The streams are represented by Lire::DlfStream objects. =head2 dlf_streams() List the DLF stream available in the DLF store. This returns a list of DlfSchema's name. =cut sub dlf_streams { my $self = $_[0]; my @streams = (); # patch from Jean-Benoit Marzio, see: # http://lists.logreport.org/pipermail/questions/2010/000861.html my @table_list = $self->{'_dbh'}->tables; foreach my $table ( @table_list) { next unless $table =~ /dlf_(.*)"/; next if $table =~ /_links$/; push @streams, $1; } return @streams; } =pod =head2 has_dlf_stream( $name ) Returns true if the DlfStore contains a DlfStream conforming to the schema $name. =cut sub has_dlf_stream { my ( $self, $name ) = @_; return grep { $_ eq $name } $self->dlf_streams(); } =pod =head2 get_stream_config( $name ) Returns the Lire::Config::Dictionary instance which contains the stream configuration for the $name DlfStream. This method will create an instance from the default if necessary. If $name isn't a valid schema name, this method will throw an error. =cut sub get_stream_config { my ( $self, $name ) = @_; check_param( $name, 'name' ); croak "schema '$name' doesn't exist" unless Lire::DlfSchema->has_schema( $name ); my $streams_config = $self->{'_config'}->get( 'streams_config' ); foreach my $config ( $streams_config->elements() ) { return $config if $config->name eq $name; } my $config = $streams_config->spec()->get( $name )->instance(); $streams_config->append( $config ); return $config; } =pod =head2 configured_dlf_streams() Returns the list of DlfStreams which are referenced by the store configuration. This is the result of dlf_streams() plus all schemas that exists and are used by one of the confiured ImportJob or DlfStreamSpec. =cut sub configured_dlf_streams { my $self = $_[0]; my @streams = ( $self->dlf_streams(), @{ $self->_import_job_streams() } ); my %done = (); while ( defined( my $s = shift @streams ) ) { next unless Lire::DlfSchema->has_schema( $s ); next if exists $done{$s}; push @streams, @{ $self->_analyser_streams( $s ) }; $done{$s} = 1; } return sort keys %done; } sub _analyser_streams { my ( $self, $name ) = @_; my @streams = (); my $cfg = $self->get_stream_config( $name ); foreach my $comp ( $cfg->spec()->components() ) { next unless $comp->isa( 'Lire::Config::DlfAnalyserSpec' ); push @streams, $comp->name() if $cfg->get( $comp->name() )->get_plugin() ne 'none'; } return \@streams; } sub _import_job_streams { my $self = $_[0]; my @streams = (); foreach my $job ( @{ $self->import_jobs() } ) { my $name = $job->converter(); push @streams, Lire::PluginManager->get_plugin( 'dlf_converter', $name )->schemas() if Lire::PluginManager->has_plugin( 'dlf_converter', $name ); } return \@streams; } =pod =head2 open_dlf_stream( $name, [$mode], [$sort_spec] ) Returns a Lire::DlfStream object that can be used to a DLF stream in the schema $name. The $mode parameter can either "r" or "w" and defaults to "r". If the mode is "w", the Lire::DlfStream is opened for writing (new Dlf records can be inserted). If the DlfStore didn't contains a stream $name, an empty one will be created. If the mode is "r", the Lire::DlfStream is opened for reading (no DLF records may be inserted). An exception will be thrown if there is no stream $name available. When the stream is opened in "r" mode, a sort order can be specified by passing a $sort_spec. A $sort_spec is a white-space delimited list of field names which should specify the sort order. Reverse sort order can be specified by prefixing the field's name by '-'. =cut sub open_dlf_stream { my ( $self, $name, $mode, $sort_spec ) = @_; check_param( $name, 'name' ); $mode ||= "r"; croak "mode should be either 'r' or 'w' not '$mode'" unless $mode eq 'r' or $mode eq 'w'; croak "no DLF stream '$name' in this store" if ( $mode eq 'r' && ! $self->has_dlf_stream( $name ) ); croak "only 'r' mode can use a sort_spec" if ( $mode ne 'r' && $sort_spec ); return new Lire::DlfStream( $self, $name, $mode, $sort_spec ); } =pod =head2 run_analysers( $stream, [ $dlf_source ] ) Runs all the configured analysers on the DLF stream $stream. $dlf_source limit the records which should be analysed. =cut sub run_analysers { my ( $self, $stream, $dlf_source ) = @_; check_param( $stream, 'stream' ); croak "no DLF stream '$stream' in this store" unless $self->has_dlf_stream( $stream ); my $config = $self->get_stream_config( $stream )->as_value(); while ( my ( $stream, $analyser ) = each %$config ) { next if $stream eq 'keep_days'; next if $analyser->{'plugin'} eq 'none'; my $process = new Lire::DlfAnalyserProcess( $self, $analyser->{'plugin'}, $analyser->{'properties'}, $dlf_source ); $process->run_analysis_job(); $self->run_analysers( $stream, $process->job_id() ); } return; } =pod =head2 clean_streams() Remove records that are days older than what is configured in the 'keep_days' parameter. =cut sub clean_streams { my ($self, $time) = @_; $time ||= time; foreach my $name ( $self->dlf_streams() ) { my $config = $self->get_stream_config( $name ); my $keep_days = $config->get( 'keep_days' )->as_value(); next unless $keep_days; my $time = $time - 86400 * $keep_days; my $stream = $self->open_dlf_stream( $name, 'w' ); $stream->clean( $time ); $stream->close(); } return; } sub _dbh { return $_[0]{'_dbh'}; } =pod =head1 REPORTS RELATED METHOD A DlfStore also contains the periodically generated reports. These reports are usually configured through the lire(1) command. The generated reports are stored in Lire XML native format by period. =head2 put_report( $job, $schedule, $report ) Saves the $report Lire::Report which was generated by $job and $schedule. Returns the filename where the report was saved. =cut sub put_report { my ( $self, $job, $schedule, $report ) = @_; check_object_param( $job, 'job', 'Lire::ReportJob' ); check_object_param( $schedule, 'schedule', 'Lire::ReportSchedule' ); check_object_param( $report, 'report', 'Lire::Report' ); my $file = $self->_report_filename( $job->name(), $schedule->period(), $report->timespan_start() ); my $dir = dirname( $file ); mkpath( [ $dir ], 0, 0755 ) unless -d $dir; CORE::open my $fh, "> $file" or die "failed to open '$file' for writing: $!\n"; $report->write_report( $fh ); CORE::close $fh; return $file; } =pod =head2 find_report_source( $job, $schedule, [$time] ) This method will returns an hash reference containing parameters on how the ReportJob $job should be generated for the ReportSchedule $schedule. The boundaries of the period are determined according to $time which detauls to now. The hash reference will contain a 'source' key as well as possible others: =over =item source Specify from what kind of source the report should be generated. Possible values are 'dlf' when the report should be generated from DLF, 'merging' when the report should be generated by merging previous XML reports and 'none' when no data is available for that period and the report cannot be generated. Note that 'merging' is only available as a source for schedule above 'daily'. i.e. 'hourly' and 'daily' reports can only be generated from DLF. Also of important is the fact that only 'daily' reports are available as a source of merging. So you need a daily report schedule to generate 'weekly', 'monthly' and 'yearly' schedule by merging. =item start The timestamp at which the available data for the period starts. This can be higher than the requested period's starting boundary. =item end The timestamp at which the available data for the period ends. This can be lower than the requested period's ending boundary. =item coverage An integer between 0 and 100 representing the ratio of data available for the requested period. For example, if only 6 hours of data are available for a 'daily' report, the 'coverage' will be 25. =item reports This key is only available when 'source' is 'merging'. It contains an array of report files which should be used as the source of merging. =item days This key is only available when 'source' is 'merging'. It contains the days for which a reports was available for merging. For example, if only 6 daily reports were available to generate a 'weekly' report, this will contain those 6 days dates in ISO format (%Y-%m-%d). =cut sub find_report_source { my ( $self, $job, $schedule, $time ) = @_; $time ||= time(); check_object_param( $job, 'job', 'Lire::ReportJob' ); check_object_param( $schedule, 'schedule', 'Lire::ReportSchedule' ); my $dlf_source = $self->_find_dlf_source( $job, $schedule, $time ); return $dlf_source if $schedule->period() =~ /^(hourly|daily)$/; my $merging_source = $self->_find_merging_source( $job, $schedule, $time ); return ( $merging_source->{'coverage'} > $dlf_source->{'coverage'} ? $merging_source : $dlf_source ); } sub _find_dlf_source { my ( $self, $job, $schedule, $time ) = @_; my $avail_start = 0; my $avail_end = 2**31; my $range = $schedule->period_range( $time ); foreach my $schema ( @{ $schedule->report_config()->schemas() } ) { next unless $self->has_dlf_stream( $schema ); my $stream = $self->open_dlf_stream( $schema, 'r' ); my $start = $stream->start_time(); my $end = $stream->end_time(); $stream->close(); next unless defined $start; next if ( $start > $range->[1] || $end < $range->[0] ); $avail_start = max( $range->[0], $start, $avail_start ); $avail_end = min( $range->[1], $end, $avail_end ); } return { 'source' => 'none', 'coverage' => 0 } unless $avail_start; return { 'source' => 'dlf', 'start' => $avail_start, 'end' => $avail_end, 'coverage' => int( ( $avail_end - $avail_start ) * 100 / ( $range->[1] - $range->[0] ) ), }; } sub _find_merging_source { my ( $self, $job, $schedule, $time ) = @_; my $source = { 'source' => 'merging', 'start' => undef, 'end' => undef, 'reports' => [], 'days' => [], 'coverage' => 0 }; my $range = $schedule->period_range( $time ); for ( my $day=$range->[0]; $day < $range->[1]; $day += 86400 ) { my $file = $self->_report_filename( $job->name(), 'daily', $day ); if ( -f $file ) { $source->{'start'} = $day unless defined $source->{'start'}; $source->{'end'} = $day + 86400; push @{$source->{'reports'}}, $file; push @{$source->{'days'}}, strftime( '%Y-%m-%d', localtime $day); } } if ( $source->{'start'} ) { $source->{'coverage'} = int( ( $source->{'end'} - $source->{'start'}) * 100 / ( $range->[1] - $range->[0] ) ); } return $source; } sub _report_filename { my ( $self, $report, $period, $time ) = @_; check_param( $report, 'report' ); check_param( $period, 'period', qr/^(hourly|daily|weekly|monthly|yearly)$/, "'period' parameter should be one of 'hourly', 'daily', 'weekly', 'monthly' or 'yearly'" ); check_param( $time, 'time', qr/^\d+$/ ); my $fmt = ""; if ( $period eq 'hourly' ) { $fmt = "%Y%m/%d/%H.xml"; } elsif ( $period eq 'daily' ) { $fmt = "%Y%m/%d.xml"; } elsif ( $period eq 'weekly' ) { $fmt = "%Y/%V.xml"; } elsif ( $period eq 'monthly' ) { $fmt = "%Y/%m.xml"; } elsif ( $period eq 'yearly' ) { $fmt = "%Y.xml"; } else { die "shouldn't be reached"; } my $calc = new Lire::WeekCalculator(); return $self->{'_store_path'} . "/${period}_reports/$report/" . $calc->strfdate( $fmt, localtime( $time ) ); } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfConverter(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: DlfStore.pm,v 1.41 2011/11/15 16:48:40 wraay Exp $ =head1 COPYRIGHT Copyright (C) 2002,2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/DlfConverterProcess.pm0000644000175000017500000003057210460673254016110 00000000000000package Lire::DlfConverterProcess; use strict; use Carp; use POSIX qw/ strftime /; use Lire::PluginManager; use Lire::Config; use Lire::DlfQuery; use Lire::Utils qw/ check_param check_object_param /; use Lire::I18N qw/ set_fh_encoding /; =pod =head1 NAME Lire::DlfConverterProcess - Object that controls the DLF conversion process =head1 SYNOPSIS use Lire::ImportJob; use Lire::DlfStore; use Lire::DlfConverterProcess; my $src = new Lire::ImportJob( "file", 'pattern' => "/var/log/messages" ); my $store = Lire::DlfStore->open( "store" ); my $process = new Lire::DlfConverterProcess( $src, $store ); $process->run_import_job(); print "Log lines read: ", $process->line_count(), "\n"; print "DLF records created: ", $process->dlf_count, "\n"; print "Errors encountered: ", $process->errors_count, "\n"; print "Ignored records: ", $process->ignored_count,"\n"; =head1 DESCRIPTION This object encapsulates the Lire DLF conversion process. It takes as parameter a Lire::ImportJob and a Lire::DlfStore. It will setup the converter and will converter the content of Lire::ImportJob to DLF which will be saved in the Lire::DlfStore. The object provides the API to the converter. Methods are also available to query information on the conversion process. =head1 new( $job, $store ); Create a Lire::DlfConverterProcess that will be used to import the log specified in Lire::ImportJob into DLF records which will be stored into Lire::DlfStore. =cut sub new { my ( $pkg, $job, $store ) = @_; check_object_param( $job, 'job', 'Lire::ImportJob' ); check_object_param( $store, 'store', 'Lire::DlfStore' ); return bless { '_job' => $job, '_store' => $store, '_convert_called' => 0, }, ref $pkg || $pkg; } =pod =head2 run_import_job( [$time] ) Import the log data from ImportJob as DLF. This method will throw an exception if it is called more than once. The $time parameter will be used to determine the time window covered by period. It defaults to the current time. =cut sub run_import_job { my ( $self, $time ) = @_; croak $self->{'_job'}->name(), " ImportJob was already processed" if $self->{'_convert_called'}; $self->{'_job_id'} = $self->{'_job'}->name() . '-' . strftime( "%Y%m%d_%H%M%S", localtime ) unless exists $self->{'_job_id'}; $self->{'_time_start'} = time; $self->_init_counters(); $self->_init_converter(); $self->_init_streams(); $self->{'_fh'} = $self->{'_job'}->log_fh( $time ); if ( $self->{'_converter'}->handle_log_lines() ) { $self->_handle_continuation(); $self->_process_log_lines( $self->{'_fh'} ); } else { $self->{'_converter'}->process_log_file( $self, $self->{'_fh'} ); } close $self->{'_fh'}; $self->{'_converter'}->finish_conversion( $self ); # Close the dlf streams foreach my $s ( values %{$self->{'_streams'}} ) { $s->close(); } $self->{'_log_stream'}->close(); $self->_save_import_stats(); $self->{'_convert_called'} = 1; return; } sub _init_converter { my $self = $_[0]; my $cname = $self->{'_job'}->converter(); croak "ImportJob ", $self->{'_job'}->name(), " doesn't have a converter defined" unless defined $cname; croak "DLF converter $cname isn't available" unless Lire::PluginManager->has_plugin( 'dlf_converter', $cname ); $self->{'_converter'} = Lire::PluginManager->get_plugin( 'dlf_converter', $cname ); $self->{'_converter'}->init_dlf_converter( $self, $self->{'_job'}->converter_config() ); return; } sub _init_streams { my $self = $_[0]; foreach my $s ( $self->{'_converter'}->schemas() ) { $self->{'_streams'}{$s} = $self->{'_store'}->open_dlf_stream( $s, "w" ); } $self->{'_log_stream'} = $self->{'_store'}->open_dlf_stream( 'lire_import_log', "w" ); return; } sub _init_counters { my $self = $_[0]; $self->{'_line_count'} = 0; $self->{'_dlf_count'} = 0; $self->{'_ignored_count'} = 0; $self->{'_error_count'} = 0; $self->{'_saved_count'} = 0; return; } sub _handle_continuation { my $self = $_[0]; my $query = new Lire::DlfQuery( 'lire_import_log' ); $query->add_field( 'line' ); $query->add_field( 'time' ); $query->add_field( 'line_no' ); $query->set_filter_clause( "type = 'continuation' AND job_name = ?", $self->{'_job'}->name() ); $query->set_sort_spec( 'time line_no' ); my $result = $query->execute( $self->{'_store'} ); while ( defined( my $row = $result->next_row_aref() ) ) { $self->{'_line_count'}++; $self->{'_converter'}->process_log_line( $self, $row->[0] ); } $self->{'_store'}->_dbh()->do( <{'_job'}->name(), $self->{'_time_start'} ); DELETE FROM dlf_lire_import_log WHERE type='continuation' AND job_name = ? AND time < ? EOSQL return; } #------------------------------------------------------------------------ # Method _process_log_lines( $fh ) # # Method which handles the read a line, process a line loop sub _process_log_lines { my ($self, $fh) = @_; my $line; my $converter = $self->{'_converter'}; while (defined ($line = <$fh>)) { # Remove DOS and/or UNIX line ending $line =~ s/\r?\n?$//; $self->{'_line_count'}++; $converter->process_log_line( $self, $line ) } return; } sub _save_import_stats { my $self = $_[0]; my $elapsed = time - $self->{'_time_start'}; my $stream = $self->{'_store'}->open_dlf_stream( 'lire_import_stats', "w"); $stream->write_dlf( { 'time_start' => $self->{'_time_start'}, 'elapsed' => $elapsed, 'job_name' => $self->{'_job'}->name(), 'job_id' => $self->{'_job_id'}, 'line_count' => $self->{'_line_count'}, 'dlf_count' => $self->{'_dlf_count'}, 'error_count' => $self->{'_error_count'}, 'ignored_count' => $self->{'_ignored_count'}, 'saved_count' => $self->{'_saved_count'}, } ); $stream->close(); return; } =pod =head2 job_id() Returns the job identifier associated to this process. =cut sub job_id { return $_[0]{'_job_id'}; } =pod =head2 dlf_store() Returns the Lire::DlfStore in which this conversion process is storing the DLF records. =cut sub dlf_store { $_[0]{'_store'} } =pod =head2 import_job() Returns the Lire::ImportJob upon which this conversion process is operating. =cut sub import_job { $_[0]{'_job'}} =pod =head2 line_count() Returns the number of lines processed. This will 0 in case the DLF converter process file and not log lines. During a processing, this is always equals to the line that is currently being converted. =cut sub line_count { $_[0]{'_line_count'}} =pod =head2 dlf_count() Returns the number of DLF records created. =cut sub dlf_count { $_[0]{'_dlf_count'} } =pod =head2 error_count() Returns the number of errors encountered in the conversion process. =cut sub error_count { $_[0]{'_error_count'} } =pod =head2 ignored_count() Returns the number of records which were ignored in the conversion process. =cut sub ignored_count { $_[0]{'_ignored_count'} } =pod =head2 saved_count() Returns the number of lines which were saved for later processing. =cut sub saved_count { $_[0]{'_saved_count'} } =pod =head1 API FOR THE DLF CONVERTERS This is the object that encapsulates the Dlf implementation and hides the complexitity of the storage framework from the DLF converter. It offers the following methods to the DLf converter. =head2 write_dlf( $schema, $dlf ) This writes the $dlf DLF record conforming the $schema's schema in the Lire::DlfStore. The schema is the schema's name (e.g. 'www'). $dlf is an hash reference. Keys are the schema's field name. Undefined value means that this field isn't available in that record. =cut sub write_dlf { my ( $self, $schema, $dlf ) = @_; check_param( $schema, 'schema' ); check_param( $dlf, 'dlf' ); my $s = $self->{'_streams'}{$schema}; croak "schema $schema wasn't defined by ", $self->{'_converter'}->name, " converter" unless defined $s; $dlf->{'dlf_source'} = $self->{'_job_id'}; $s->write_dlf( $dlf ); $self->{'_dlf_count'}++; return; } =pod =head2 save_log_line( $line ) Method that should be used to save $line for a future processing run of the converter on the same Lire::ImportJob. =cut sub save_log_line { my ( $self, $line ) = @_; check_param( $line, 'line' ); croak "only DLF converter handling log lines can save log line" unless $self->{'_converter'}->handle_log_lines(); $self->{'_saved_count'}++; $self->{'_log_stream'}->write_dlf( { 'time' => time(), 'job_name' => $self->{'_job'}->name(), 'job_id' => $self->{'_job_id'}, 'line_no' => $self->{'_line_count'}, 'type' => 'continuation', 'line' => $line, } ); return; } =pod =head2 ignored_log_line( $line, [ $reason ] ) Method that can be used by the Lire::DlfConverter to report that the '$line' log line was ignored during that processing. The reason why the line was ignored can be given in $reason. For example, syslog-based converter should use that method to report lines that are for another 'service' than theirs. =cut sub ignore_log_line { my ( $self, $line, $reason ) = @_; $reason ||= "Unknown reason"; check_param( $line, 'line' ); $self->{'_ignored_count'}++; $self->{'_log_stream'}->write_dlf( { 'time' => time(), 'job_name' => $self->{'_job'}->name(), 'job_id' => $self->{'_job_id'}, 'line_no' => $self->{'_line_count'}, 'type' => 'ignored', 'line' => $line, 'msg' => $reason, } ); return; } =pod =head2 error( $error_msg, [ $line ] ); Method that should be used by the Lire::DlfConveter to report that an error was encountered when processing the Lire::ImportJob. $error_msg should be used to report the nature of the error. The $line parameter should be used by converter operating on lines to associate the error message to a particular line. =cut sub error { my ( $self, $error_msg, $line ) = @_; check_param( $error_msg, 'error_msg' ); $self->{'_error_count'}++; $self->{'_log_stream'}->write_dlf( { 'time' => time(), 'job_name' => $self->{'_job'}->name(), 'job_id' => $self->{'_job_id'}, 'line_no' => $self->{'_line_count'}, 'type' => 'error', 'line' => defined $line ? $line : '', 'msg' => $error_msg, } ); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfStore(3pm) Lire::DlfConverter(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: DlfConverterProcess.pm,v 1.18 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Aggregator.pm0000644000175000017500000004632310460673253014236 00000000000000package Lire::Aggregator; use strict; use base qw/ Lire::ReportOperator /; use Lire::ReportOperator; use constant MERGE_INITED => 1; use constant MERGE_FINISHED => 2; use Carp; =pod =head1 NAME Lire::Aggregator - Base class for all aggregator operators =head1 SYNOPSIS use base qw/ Lire::Aggregator /; =head1 DESCRIPTION The Lire::Aggregator is the base class for all the aggregator operators available in Lire. It implements behavior common to all the aggregator as well as defining some methods that need to be implemented by subclasses. In Lire, an aggregator is an operator which will group DLF records. Other operators like avg or sum will then compute values in these groups of DLF records. Aggregators can be nested to compute values on hierarchical groups. =head1 METHODS =head2 ops( [$new_ops] ) Returns the operators contained in this aggregator. The returned value is a reference to an array of Lire::ReportOperator objects. If the $new_ops is used, it changes the content of this aggragagor to these new values. $new_ops should be a reference to an array containing Lire::ReportOperator objects. =cut sub ops { my ( $self, $ops ) = @_; if ( @_ == 2 ) { croak "$ops isn't an array reference" unless UNIVERSAL::isa( $ops, "ARRAY" ); croak "fields array is empty" if @$ops == 0; foreach my $op ( @$ops ) { croak "$op isn't of type Lire::ReportOperator" unless UNIVERSAL::isa( $op, "Lire::ReportOperator" ); } $self->{'ops'} = $ops; } return $self->{'ops'}; } =pod =head2 op_by_name( $name ) Returns the operator named $name in this aggregator. An exception is thrown if there is no such operator. =cut sub op_by_name { my ( $self, $name ) = @_; # Check in ops foreach my $op ( @{$self->{'ops'}} ) { return $op if $op->name eq $name; } croak "No operation named $name\n"; } =pod =head2 is_name_defined( $name ) Returns true if this aggregator contains an operator named $name. =cut sub is_name_defined { my ( $self, $name ) = @_; return 1 if $name eq $self->name(); # Check in ops and aggregator's children foreach my $p ( @{$self->{'ops'}} ) { return 1 if $p->name() eq $name; if ( $p->isa( 'Lire::Aggregator' ) ) { return 1 if $p->is_name_defined( $name ); } } return 0; } =pod =head1 METHODS FOR SUBCLASSES =cut #------------------------------------------------------------------------ # Method init( %params ) # # Initialize the ops attribute. sub init { my ($self, %params) = @_; $self->{'ops'} = []; $self->SUPER::init( %params ); return; } =pod =head2 print( $fh, $pfx ) This methods implements the print() method required by Lire::ReportOpetor. It prints the XML element named after op() and takes care of writing the XML representation of all the children operation. It also takes care of writing the name and label attribute. Other attributes can be added to the XML element by overriding the xml_attrs() method. Other children elements could be added to the output stream by overriding the print_content() method. =cut sub print { my ( $self, $fh, $pfx ) = @_; $fh ||= \*STDOUT; $pfx ||= 0; my $prefix = " " x $pfx; my $attrs = $self->xml_attrs; print $fh $prefix, 'op; print $fh ' ', $attrs if length $attrs; print $fh qq{ label="$self->{'label'}"} if $self->{'label'}; print $fh ">\n"; $self->print_content( $fh, $pfx + 1); print $fh $prefix, "op, ">\n"; } =pod =head2 xml_attrs() This method can be used to write additional XML attributes. The returned string will be output in the XML element. =cut sub xml_attrs { return ""; } =pod =head2 print_content( $fh, $pfx ) This method prints the operators contained in this aggregator. It can be overriden to add some other elements. =cut sub print_content { my ( $self, $fh, $pfx ) = @_; foreach my $o ( @{$self->{'ops'}} ) { $o->print( $fh, $pfx ); } } =pod =head2 create_group_info( $info ) FIXME Subclasses have to override the create_categorical_info() method for this implementation. =cut sub create_group_info { my ( $self, $info ) = @_; $info = $self->maybe_nest_group_info( $info ); $self->create_categorical_info( $info ); foreach my $op ( @{$self->ops} ) { if ( $op->isa( 'Lire::Aggregator' ) ) { $op->create_group_info( $info ); } else { $op->create_numerical_info( $info ); } } } =pod =head2 create_categorical_info( $info ) This method is used by the implementation of create_group_info() to add the categorical ColumnInfo provided by the aggregator. =cut sub create_categorical_info { croak "unimplemented create_categorical_info() in ", ref $_[0]; } #------------------------------------------------------------------------ # Method maybe_nest_group_info( $info ) # # This method should be used by subclasses in their create_group_info() # implementation to select the GroupInfo to which they should add their # ColumnInfo. # # This method takes care of creating a GroupInfo if the aggregator has a # parent. It returns the GroupInfo object to which the aggregator should # add its ColumnInfo objects. # sub maybe_nest_group_info { my ( $self, $info ) = @_; if ( $self->parent ) { return $info->create_group_info( $self->name ); } else { return $info; } } =pod =head2 create_entries( $subreport ) This method is used by Lire::ReportSpec to fill the Lire::Report::Subreport with the entries when creating the subreport. The $subreport parameter contains the Subreport object to which the subreport's entries should get added. This method will only be called on the top-level aggregator in the report. =cut sub create_entries { my ( $self, $subreport ) = @_; if ( $self->{'store'} ) { my $query = new Lire::DlfQuery( $self->report_spec()->schema()->id() ); foreach my $schema ( @{ $self->report_spec()->joined_schemas() } ) { $query->join_stream( $schema ); } $self->build_query( $query ); my $expr = $self->report_spec()->filter_spec(); if ( $expr ) { $query->set_filter_clause( $expr->sql_expr(), @{$expr->sql_params()} ); } $self->build_table( $self->{'store'}, $query, $subreport ); } elsif ( defined $self->{'_state'} ) { # Merging croak "end_merge() wasn't called" unless $self->{'_state'} == MERGE_FINISHED; $subreport->nrecords( $self->{'data'}[1] ); $subreport->missing_cases( $self->{'data'}[3] ); $self->set_summary_values( $subreport, $self->{'data'}[0] ); $self->create_group_entries( $subreport, $self->{'data'}[2] ); } return; } =pod =head2 build_query( $query ) FIXME =cut sub build_query { my ($self, $query ) = @_; $query->add_aggr_field( '_lr_nrecords', 'count(*)' ) unless grep { $_->isa( 'Lire::Aggregator' ) } @{$self->ops()}; foreach my $op ( @{ $self->ops() }) { $op->build_query( $op->isa( 'Lire::Aggregator' ) ? $query->create_nested_query() : $query ); } } sub build_table_summary { my ( $self, $store, $query, $table ) = @_; my $result = $query->execute_summary( $store ); my $summary = $result->next_row(); $table->nrecords( $summary->{'_lr_nrecords'} ); $self->set_group_summary( $table, $summary ); } =pod =head2 set_group_summary( $group, $row ) FIXME =cut sub set_group_summary { my ( $self, $group, $row ) = @_; $group->nrecords( $row->{'_lr_nrecords'} ); $self->_set_aggregate_summary_values( $group, $row ); } sub _set_aggregate_summary_values { my ( $self, $group, $row ) = @_; foreach my $op ( @{$self->ops()} ) { if ( $op->isa( 'Lire::Aggregator' ) ) { $op->_set_aggregate_summary_values( $group, $row ); } else { my $parent = $group->parent_entry() ? $group->parent_entry()->group() : $group; my $value = $op->create_value( $parent, $row ); $group->set_summary_value( $op->name(), %$value ); } } } sub _set_store { my ( $self, $store ) = @_; $self->{'store'} = $store; return; } sub build_table { my ( $self, $store, $query, $table ) = @_; $self->build_table_summary( $store, $query, $table ) unless $self->parent(); my $result = $query->execute( $store ); ROW: while (defined (my $row = $result->next_row() ) ) { my $group; if ( $self->parent() ) { my $p_name = defined $self->parent()->parent() ? $self->parent()->name() : 'table'; my $p_entry = $table->find_entry( $p_name, $row ); next ROW unless defined $p_entry; $group = $p_entry->data_by_name( $self->name() ); } else { $group = $table; } my $entry = $self->create_entry( $group, $row ); next ROW unless defined $entry; foreach my $op ( @{$self->ops()} ) { if ( $op->isa( 'Lire::Aggregator' ) ) { my $group = $entry->create_group(); $op->set_group_summary( $group, $row ); } else { my $value = $op->create_value( $entry->group(), $row ); $entry->add_value( $value ); } } } my $i=0; my $nqueries = $query->nested_queries(); foreach my $op ( grep { $_->isa( 'Lire::Aggregator' ) } @{$self->ops()}) { $op->build_table( $store, $nqueries->[$i++], $table ); } } =pod =head2 create_entry( $group, $row ) FIXME =cut sub create_entry { my ( $self, $group, $row ) = @_; croak( "Unimplemented create_entry() in ", ref $self ); } =pod =head1 MERGING AGGRATOR API It defines additional methods required by Aggregator implementation to be able to merge data.. The base Aggregator implementation takes care of merging the summary information included in the Lire XML reports. The merging specifics to the aggregator should be implemented in the init_agggregator_data(), update_aggregator_data() and end_aggregator_data() methods. This class also takes care of the case when the aggregator is the top-level aggregator, that is the immediate child of the report-calc-spec element in the report specification), =head1 IMPLEMENTATION OF Lire::ReportOperator MERGING METHODS =pod =head1 init_merge( $period_start, $period_end ) The default implementation makes sure that all contained operators are inited. Implementation of specific aggregator must chain up to this method, if they override it. =cut sub init_merge { my $self = $_[0]; foreach my $op ( @{$self->ops()} ) { $op->init_merge(); } $self->{'data'} = $self->init_group_data(); $self->{'_state'} = MERGE_INITED; return $self; } #------------------------------------------------------------------------ # Methode merge_subreport( $subreport ) # # This method will be called once for every subreport to be merged. # # $subreport is the Lire::Report::Subreport to merged. # # Method called by lr_xml_merge(1) sub merge_subreport { my ( $self, $subreport ) = @_; croak "init_merge() wasn't called" unless $self->{'_state'} == MERGE_INITED; $self->merge_group_data( $subreport, $self->{'data'} ); return $self; } =pod =head2 end_merge() The default implementation makes sure that all operators gets the end_report() event. Subclasses should chain up to this method, if they override it. =cut sub end_merge { my ( $self ) = @_; croak "init_merge() wasn't called" unless $self->{'_state'} == MERGE_INITED; $self->end_group_data( $self->{'data'} ); $self->{'_state'} = MERGE_FINISHED; return $self; } =pod =head2 init_group_data() The Aggregator implements init_group_data(). It takes care of computing the summary information. Subclass does the equivalent in init_aggregator_data(). =cut sub init_group_data { my $self = $_[0]; # Elements of the array # 0 = summary data # 1 = nrecords # 2 = subclass' data # 3 = missing-cases return [ $self->init_summary_data(), 0, $self->init_aggregator_data(), 0 ]; } =pod =head2 merge_group_data( $value, $data ) The Aggregator implements merge_group_data(). It takes care of merging the summary information. Subclass does the equivalent in merge_aggregator_data(). =cut sub merge_group_data { my ( $self, $value, $data ) = @_; croak "value should be of type Lire::Report::Group, not $value\n" unless UNIVERSAL::isa( $value, "Lire::Report::Group" ); $data->[1] += $value->nrecords(); $data->[3] += $value->missing_cases(); $self->merge_summary_data( $value, $data->[0] ); $self->merge_aggregator_data( $value, $data->[2] ); return; } =pod =head2 end_group_data($data) The Aggregator implements end_group_data(). It takes care of computing the summary information. Subclass does the equivalent in end_aggregator_data(). =cut sub end_group_data { my ( $self, $data ) = @_; $self->end_summary_data( $data->[0] ); $self->end_aggregator_data( $data->[2] ); return } =pod =head2 add_entry_value( $entry, $data ) This method will make sure that the entries of nested aggregator are wrapped up in a Lire::Report::Group element. There is no reason to override that method since the entries of the aggregator are added in the create_group_entries() method. =cut sub add_entry_value { my ( $self, $entry, $data ) = @_; my $group = $entry->create_group(); $group->nrecords( $data->[1] ); $group->missing_cases( $data->[3] ); $self->set_summary_values( $group, $data->[0] ); $self->create_group_entries( $group, $data->[2] ); return; } # ------------------------------------------------------------------------ # METHODS FOR SUMMARY STATISTICS COMPUTATION # # This class defines several methods that are to be used in subclasses # to compute the summary statistics that are included in Lire XML # report. Those summary statistics are only computed by Aggregate # operator (those that compute an aggregated value like avg, sum, # etc.). The summary value is computed over all the records seen by the # aggregator instead of only the grouped records. #------------------------------------------------------------------------ # Method init_summary_data () # # Returns a summary data structure. sub init_summary_data { my ( $self, $data ) = @_; $data ||= {}; foreach my $op ( @{$self->ops()} ) { if ( $op->isa( 'Lire::Aggregate' ) ) { $data->{$op->name} = $op->init_group_data(); } elsif ( $op->isa( 'Lire::Aggregator' ) ) { $op->init_summary_data( $data ); } } return $data; } #------------------------------------------------------------------------ # Method merge_summary_data ( $group, $summary_data ) # # This method updates the Aggregate's summary data structures. sub merge_summary_data { my ( $self, $group, $data ) = @_; foreach my $op ( @{$self->ops()} ) { if ( $op->isa( 'Lire::Aggregate' ) ) { my $value = $group->get_summary_value( $op->name() ); unless ($value) { warn( "missing summary value for ", $op->name(), " operator"); next; } $op->merge_group_data( $value, $data->{$op->name()} ); } elsif ( $op->isa( 'Lire::Aggregator' ) ) { $op->merge_summary_data( $group, $data ); } } } #------------------------------------------------------------------------ # end_summary_data( $summary_data ) # # This method calls end_group_data() on all aggregates' data structures. sub end_summary_data { my ( $self, $data ) = @_; foreach my $op ( @{$self->ops()} ) { if ( $op->isa( 'Lire::Aggregate' ) ) { $op->end_group_data( $data->{$op->name} ); } elsif ( $op->isa( 'Lire::Aggregator' ) ) { $op->end_summary_data( $data ); } } } #------------------------------------------------------------------------ # set_summary_values( $group, $summary_data ) # # Make sure all operators sets their summary value sub set_summary_values { my ( $self, $group, $data ) = @_; foreach my $op ( @{$self->ops()} ) { if ( $op->isa( 'Lire::Aggregate' ) ) { my $v = $op->create_value( $group, $op->data2dlf( $data->{$op->name()} ) ); $group->set_summary_value( $op->name(), %$v ); } elsif ( $op->isa( 'Lire::Aggregator' ) ) { $op->set_summary_values( $group, $data ); } } } #------------------------------------------------------------------------ # Method get_summary_value_string( $name ) # # Returns a code string which can be used to access the summary # data item of operator $name. sub get_summary_value_string { my ( $self, $name ) = @_; return "->{'" . $name . "'}"; } =pod =head1 METHODS THAT SHOULD BE IMPLEMENTED BY SUBCLASSES FOR MERGING =head2 init_aggregator_data() This is the equivalent of init_group_data() and is called from Aggregator's implementation of init_group_data(). =cut sub init_aggregator_data { croak "Unimplemented init_aggregator_data() method in ", ref $_[0], "\n"; } =pod =head2 merge_aggregator_data( $value, $data ) This method is the equivalent than merge_group_data() and is called from Aggregator's implementation of merge_group_data(). =cut sub merge_aggregator_data { croak "Unimplemented merge_aggregator_data() method in ", ref $_[0], "\n"; } =pod =head2 end_aggregator_data( $data ) This method is the equivalent of the end_group_data() and is called from Aggregator's implementation of end_group_data(). =cut sub end_aggregator_data { croak "Unimplemented end_aggregator_data() method in ", ref $_[0], "\n"; } =head2 create_group_entries( $group, $data ) In this method, the aggregator should add one Lire::Report::Entry object for every group merged by the aggregator. $group is an instance of Lire::Report::Group to which the entries should be added. $data is the data structure returned by init_group_data() for the group in which the aggregator is nested (or the only structure that was created when the aggregator is the top-level aggregator). In this method, the aggregator must make sure to call add_entry_value() on its contained operators for each entry created. =cut sub create_group_entries { croak "Unimplemented create_group_entries method in ", ref $_[0], "\n"; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::Aggregate(3pm), Lire::ReportOperator(3pm), Lire::Group(3pm), Lire::Timegroup(3pm), Lire::Timeslot(3pm), Lire::Rangegroup(3pm) =head1 AUTHORS Francis J. Lacoste Wolgang Sourdeau =head1 VERSION $Id: Aggregator.pm,v 1.29 2006/07/23 13:16:27 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/OldDlfAdapter.pm0000644000175000017500000001623010460673255014615 00000000000000package Lire::OldDlfAdapter; use strict; use base qw/ Lire::DlfConverter /; use Carp; use Fcntl; use File::Basename qw/ basename /; use Symbol; use Lire::DlfSchema; use Lire::Utils qw/ tempdir check_param /; use Lire::DataTypes qw/ check_superservice /; use File::Path qw/rmtree/; =pod =head1 NAME Lire::OldDlfAdapter - Module which bridges with old-style DLF converters =head1 SYNOPSIS my $converter = new Lire::OldDlfAdatper( "www", "/usr/libexec/lire/converters/combined2dlf" ); =head1 DESCRIPTION This class can be used to integrate the script-based old-style DLF converters to the new API. =head2 new( $schema, $script ) The constructor takes the schema's supported by the script and the path to the script which implements the DLF converter. =cut sub new { my ( $class, $schema, $script ) = @_; check_param( $schema, 'schema', sub { Lire::DlfSchema->has_schema( $_[0] ); }, 'invalid schema name' ); check_param( $script, 'script', sub { -x $_[0] }, 'script is not executable' ); my ($name) = basename( $script ); croak "invalid script name: $script (should be 2dlf)" unless $name =~ /^(\w+)2dlf$/; my $self = bless { '_name' => $1, '_script' => $script, '_schema' => $schema, }, ref $class || $class; return $self; } #------------------------------------------------------------------------ # Method name() # # Required by Lire::DlfConverter. sub name { $_[0]{'_name'}; } =pod =head2 script() Returns the path to the script which is used to create the DLF records =cut sub script { $_[0]{'_script'}; } #------------------------------------------------------------------------ # Method title() # # Required by Lire::DlfConverter. sub title { "$_[0]{'_name'} log file"; } #------------------------------------------------------------------------ # Method description() # # Required by Lire::DlfConverter. sub description { "Adapter for old-style DLF converter $_[0]{'_script'}."; } #------------------------------------------------------------------------ # Method schemas() # # Required by Lire::DlfConverter. sub schemas { ( $_[0]{'_schema'} ); } #------------------------------------------------------------------------ # Method handle_log_lines() # # Required by Lire::DlfConverter. sub handle_log_lines { 1 } #------------------------------------------------------------------------ # Method init_dlf_converter( $process ) # # Required by Lire::DlfConverter. sub init_dlf_converter { my ( $self, $process ) = @_; my $schema = Lire::DlfSchema::load_schema( $self->{'_schema'} ); $self->{'_field_names'} = []; foreach my $f ( $schema->fields ) { push @{$self->{'_field_names'}}, $f->name; } $self->{'_dlffile'} = undef; $self->{'_logfile'} = undef; $self->{'_tmpdir'} = tempdir( $self->{'_name'} . "_XXXXXX" ); open( $self->{'_dlffile'}, "+> $self->{'_tmpdir'}/$self->{'_name'}.dlf" ) or die "can't open temporary dlf file: $!\n"; open( $self->{'_logfile'}, "+> $self->{'_tmpdir'}/$self->{'_name'}.log" ) or die "can't open temporary log file: $!\n"; my ($read_fh, $write_fh) = ( gensym, gensym ); pipe( $read_fh, $write_fh ) or die "pipe failed: $!\n"; $self->{'_convert_pid'} = fork; die "fork failed: $!\n" unless defined $self->{'_convert_pid'}; if ( !$self->{'_convert_pid'} ) { close $write_fh; open( STDIN, "<&". fileno( $read_fh ) ) or die "cannot redirect STDIN to pipe: $!\n"; close $read_fh; open( STDOUT, ">&" . fileno( $self->{'_dlffile'} ) ) or die "cannot redirect STDOUT to file: $!\n"; close $self->{'_dlffile'}; open( STDERR, ">&" . fileno( $self->{'_logfile'} ) ) or die "cannot redirect STDERR to file:\n"; close $self->{'_logfile'}; exec( $self->{'_script'} ) or die "exec $self->{'_script'} failed: $!\n"; } close $read_fh; $self->{'_convert_fh'} = $write_fh; } #------------------------------------------------------------------------ # Method process_log_line( $process, $line ) # # Required by Lire::DlfConverter. sub process_log_line { my ( $self, $process, $line ) = @_; print {$self->{'_convert_fh'}} $line, "\n" or die "error while sending data to old dlf converter: $!\n"; return; } #------------------------------------------------------------------------ # Method finish_conversion( $process ) # # Required by Lire::DlfConverter. sub finish_conversion { my ( $self, $process ) = @_; close $self->{'_convert_fh'} or die "closing pipe failed: $!\n"; waitpid $self->{'_convert_pid'}, 0 or die "waitpid failed: $!\n"; my $status = $?; $self->_import_dlf( $process ); $self->_import_errors( $process ); die "old-style DLF converter exited with non-zero status: $?\n" if $status; rmtree( $self->{'_tmpdir'} ); return; } sub _import_dlf { my ($self, $process) = @_; my $fh = $self->{'_dlffile'}; seek $fh, 0, 0 or die "can't rewind temporary DLF file: $!\n"; my $field_count = @{$self->{'_field_names'}}; my $line; while ( defined( $line = <$fh>) ) { chomp $line; my %r = (); my $i=0; foreach my $v ( split / /, $line ) { $r{$self->{'_field_names'}[$i++]} = $v eq 'LIRE_NOTAVAIL' ? undef : $v; } if ($i != $field_count ) { $process->error( "only $i fields when $field_count expected", $line ); } else { $process->write_dlf( $self->{'_schema'}, \%r ); } } } sub _import_errors { my ( $self,$process ) = @_; my $fh = $self->{'_logfile'}; seek $fh, 0, 0 or die "can't rewind temporary log file: $!\n"; my $line; while (defined ( $line = <$fh> ) ) { chomp $line; my ($super,$service,$id,$prog,$level, $msg ) = split /\s+/, $line, 6; next unless $level =~ /^(crit|err|warning)$/; $process->error( $msg ); } } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfConverterProcess(3pm), Lire::DlfStore(3pm), Lire::ImportJob(3pm), Lire::PluginManager(3pm), Lire::DlfConverter(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: OldDlfAdapter.pm,v 1.17 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/UI.pm0000644000175000017500000002614610460673256012475 00000000000000package Lire::UI; use strict; use Curses; use Curses::UI; use Curses::UI::Common; use File::Basename; use Locale::TextDomain 'lire'; use Text::Wrap qw/ wrap /; use Lire::Config; use Lire::DlfStore; use Lire::Utils qw/check_object_param /; use Lire::Error qw/ an_error_occured /; use Lire::Config::Build qw/ ac_info /; use Lire::Config::ConfigFile; use Lire::UI::Prefs; use Lire::UI::Widget; use Lire::UI::Utils qw/button_box_width/; =pod =head1 NAME Lire::UI - Interface to a DLF store =head1 SYNOPSIS use Lire::Config; use Lire::UI; use Lire::PluginManager; Lire::Config->init(); Lire::PluginManager->register_default_plugins(); my $ui = Lire::UI->new(); $ui->curses_ui()->clear_on_exit( 1 ); exit( $ui->mainloop() ); =head1 DESCRIPTION The Lire::UI object creates a Curses::UI application. =cut sub new { my $class = $_[0]; my $ui = new Curses::UI(); my $self = bless { '_ui' => $ui }, $class; $ui->userdata( $self ); $self->_create_menubar(); $self->_create_quickstart_win(); return $self; } =pod =head2 curses_ui() Returns the Curses::UI object used for the interface. =cut sub curses_ui { my $self = $_[0]; return $self->{'_ui'}; } =pod =head2 edit_value_dialog( $value, [$title] ) Opens a modal dialog that can edit the Lire::Config::Value $value. The dialog has an OK and Cancel button and contains one Lire::UI::Widget appropriate for the $value type. The method returns true when the OK button was selected, false otherwise. =cut sub edit_value_dialog { my ( $self, $value, $title ) = @_; check_object_param( $value, 'value', 'Lire::Config::Value' ); $title ||= __x( 'Editing {component}', 'component' => $value->summary() ); my $retvalue = 0; my $name = "edit_value_dialog_$value"; my $dlg = $self->{'_ui'}->add( $name, 'Curses::UI::Window', '-title' => $title, '-border' => 1, '-padtop' => 2, '-pad' => 1, '-ipad' => 1 ); $dlg->set_binding( sub { $dlg->loose_focus() }, CUI_ESCAPE ); $dlg->add( 'widget', 'Lire::UI::Widget', '-releasefocus' => 1, 'value' => $value, '-width' => $dlg->canvaswidth() - 1, '-height' => $dlg->canvasheight() - 2 ); my $buttons = [ {'-label' => __( '< Cancel >' ), '-onpress' => sub { $dlg->loose_focus() } }, {'-label' => __( '< OK >' ), '-onpress' => sub { $retvalue = 1; $dlg->loose_focus() } } ]; my $bb_width = button_box_width( $buttons ); $dlg->add( 'buttons', 'Curses::UI::Buttonbox', '-buttons' => $buttons, '-x' => $dlg->canvaswidth() - $bb_width - 10, '-y' => $dlg->canvasheight() - 1, '-width' => $bb_width, '-height' => 1 ); $dlg->modalfocus(); $self->{'_ui'}->delete( $name ); $self->{'_ui'}->draw( 1 ); return $retvalue; } sub _create_quickstart_win { my $self = $_[0]; my $win = $self->{'_ui'}->add( 'quickstart_win', 'Window', '-y' => 1, '-border' => 1 ); my $text = $win->add( 'text_viewer', 'TextViewer', '-vscrollbar' => 1, '-text' => __( <<'_EOD' ) ); Welcome to Lire, the versatile log-analyser! This is a quick graphical user-interface for configuring Lire and for managing DLF stores (the directories where your reports and logs data is stored and handled). To access the menubar, press or . To wander between the different widgets contained in a window or a dialog, use the key. When done, press or , choose the Lire widget and choose quit. Your changes will be savely stored. The first time you use Lire, you are encouraged to have a look at and to modify the global Lire preferences to ensure they suit your needs. Go to the "Lire->Preferences..." menu to do so. If you want to generate periodical reports, you should create a new DLF store and then add it import jobs and report jobs. Import jobs are meant to parse and convert specified logfiles into the store database for further processing, while report jobs process the gathered data to produce and format reports. Be sure you have some lr_cron calls in your personal crontab. If you think you could gain significant storage room after a while, you can also clear old records since Lire will still be able to produce periodical reports by merging previous daily reports. _EOD $win->focus(); return; } sub _create_menubar { my $self = $_[0]; my $menu = [ { '-label' => 'Lire', '-submenu' => [ { '-label' => __( 'About Lire...' ), '-value' => \&_lire_about_cb }, { '-label' => __( 'Preferences...' ), '-value' => \&_lire_prefs_cb }, { '-label' => __( 'Quit' ), '-value' => \&_lire_quit_cb } ] }, { '-label' => 'Store', '-submenu' => [ { '-label' => __( 'New...' ), '-value' => \&_store_new_cb }, { '-label' => __( 'Open...' ), '-value' => \&_store_open_cb } ] }, ]; my $menubar = $self->{'_ui'}->add( 'menubar', 'Menubar', '-menu' => $menu ); $self->{'_ui'}->set_binding( \&_focus_menubar_cb, KEY_F(10), "\cx" ); return; } sub _update_store_menu { my ( $self, $active ) = @_; my $submenu = ( $active ? [ { '-label' => __( 'Close' ), '-value' => \&_store_close_cb } ] : [ { '-label' => __( 'New...' ), '-value' => \&_store_new_cb }, { '-label' => __( 'Open...' ), '-value' => \&_store_open_cb } ] ); my $menubar = $self->{'_ui'}->getobj( 'menubar' ); $menubar->{'-menu'}[1]{'-submenu'} = $submenu; return; } sub mainloop { my $self = $_[0]; local $SIG{'__WARN__'} = sub { local $Text::Wrap::columns = 60; my $msg = wrap( '', '', shift ); $self->{'_ui'}->status( $msg ); sleep 2; }; eval { $self->{'_ui'}->mainloop(); }; my $exit_code = $@; die "Code reached unexpectedly... Beware, maybe your computer is haunted." unless $exit_code; my $store_win = $self->{'_ui'}->getobj( 'store_win' ); $store_win->store()->close() if defined $store_win; return 0 if ( $exit_code eq "Quit\n" ); $self->{'_ui'}->error( an_error_occured( $exit_code ) ); return 1; } sub cleanup { my $self = $_[0]; $self->{'_ui'}{'-userdata'} = undef; $self->{'_ui'} = undef; return; } sub _get_config_file { my $self = $_[0]; my $cfg_file = "$ENV{'HOME'}/.lire/config.xml"; my $found = grep { $_ eq $cfg_file } Lire::Config->config_files(); unless ( $found ) { my $file = new Lire::Config::ConfigFile( 'spec' => Lire::Config->config_spec(), 'filename' => $cfg_file ); my $dirname = dirname( $cfg_file ); mkdir $dirname, 0700 unless ( -d $dirname ); $file->save(); Lire::Config->add_config_file( $cfg_file ); } return Lire::Config->get_config_file( $cfg_file ); } # callback functions sub _lire_about_cb { my $widget = $_[0]; my $ui = $widget->root(); $ui->dialog('-title' => __x( 'About Lire {version}', 'version' => ac_info( 'VERSION' ) ), '-message' => __x( <<'_EOF','version' => ac_info( 'VERSION' ) ) ); Lire {version} - the versatile log-analyser http://www.logreport.org/ Lire is developed and maintained by the LogReport Development Team Copyright (c) 2000-2004 Stichting Logreport Foundation Some parts of Lire are also copyrighted by third-parties. Please consult the AUTHORS file in the Lire distribution for the complete list. _EOF return; } sub _lire_prefs_cb { my $widget = $_[0]; my $ui = $widget->root(); my $prefs = new Lire::UI::Prefs( $ui, $ui->userdata()->_get_config_file()); $prefs->show(); return; } sub _lire_quit_cb { die "Quit\n"; } sub _store_new_cb { my $widget = $_[0]; my $ui = $widget->root(); my $store_path = $ui->filebrowser( '-title' => __( 'Create a New Store...' ), '-editfilename' => 1 ); return unless defined $store_path; my $store = eval { Lire::DlfStore->open( $store_path, 1 ) }; if ( $@ ) { $ui->error( __x( "Error creating store:\n {error}", 'error' => $@ ) ); return; } $ui->userdata()->_open_store_window( $store ); return; } sub _open_store_window { my ( $self, $store ) = @_; my $store_win = $self->{'_ui'}->add( 'store_win', 'Lire::UI::StoreWindow', 'store' => $store, '-y' => 1 ); $self->_update_store_menu( 1 ); $store_win->focus(); return; } sub _store_open_cb { my $widget = $_[0]; my $ui = $widget->root(); my $store_path = $ui->dirbrowser( '-title' => __( 'Choose a Store...' ) ); return unless defined $store_path; my $store = eval { Lire::DlfStore->open( $store_path ) }; if ( $@ ) { $ui->error( __x( "Error opening store:\n {error}", 'error' => $@ ) ); return; } $ui->userdata()->_open_store_window( $store ); return; } sub _store_close_cb { my $widget = $_[0]; $widget->root()->getobj( 'store_win' )->store()->close(); $widget->root()->delete( 'store_win' ); $widget->root()->userdata()->_update_store_menu(0); return; } sub _focus_menubar_cb { my $widget = $_[0]; $widget->root()->focus( 'menubar' ); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO lire(1), Curses::UI(3pm) =head1 VERSION $Id: UI.pm,v 1.25 2006/07/23 13:16:30 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/ReportParser/0000755000175000017500000000000011677607767014340 500000000000000lire-2.1.1/all/lib/Lire/ReportParser/AsciiWriter.pm0000644000175000017500000003054310460673257017032 00000000000000package Lire::ReportParser::AsciiWriter; use strict; use base qw/ Lire::ReportParser::RowColHandler /; use Text::Wrap qw/ wrap /; use Lire::I18N qw/ set_fh_encoding /; use Lire::ReportParser::AsciiDocBookFormatter qw/dbk2txt/; sub new { my $self = shift->SUPER::new( @_, 'summary_when' => 'after' ); my %args = @_; $self->{'columns'} = $args{'columns'} || 74; $self->{'max_name_len'} = $args{'max_name_length'} || 180; $self->{'_fh'} = $args{'output'} || \*STDOUT; $self->{'_encoding'} = $args{'encoding'} || ''; set_fh_encoding( $self->{'_fh'}, $self->{'_encoding'} ) if $self->{'_encoding'}; return $self; } sub report_start { my $self = shift; $self->SUPER::report_start( @_ ); $self->{'print_timespan'} = 1; return; } sub print_text { my $self = shift; my $fh = $self->{'_fh'}; print $fh @_; } sub handle_timespan { my ( $self, $timespan ) = @_; if ( $self->{'print_timespan'} ) { my $date = $self->current_date(); my $timespan = $self->current_timespan(); $self->print_text( "Report generated: ", $date->{'date'}, "\n" ) if $date; if ( $timespan ) { $self->print_text( "Reporting on period:\n", $timespan->{'timespan'}, "\n\n" ); } $self->{'print_timespan'} = 0; } } sub handle_title { my ( $self, $title ) = @_; # Trim the title $title =~ s/^\s*//; $title =~ s/\s*$//; if ($self->in_element( "lire:section" ) ) { # Section's title my $len = length $title; if ( $len > $self->{'columns'} - 12 ) { local $Text::Wrap::columns = $self->{'columns'} - 12; $self->print_text( wrap( " ", " ", $title ), "\n", " ", "-" x ($self->{'columns'} - 12), "\n\n" ); } else { my $pad = int( ($self->{'columns'} - $len) / 2); $self->print_text( ' ' x $pad, $title, "\n", ' ' x $pad, '-' x $len, "\n\n" ); } } else { local $Text::Wrap::columns = $self->{'columns'} - 12; $self->print_text( wrap( " ", " ", $title ), "\n\n" ); } } sub section_end { my $self = shift; $self->print_text( " No subreports were generated for this section.\n\n" ) if ( ! $self->current_section_subreport_count() ); $self->SUPER::section_end( @_ ); } sub subreport_start { my $self = shift; $self->SUPER::subreport_start( @_ ); $self->{'printed_description'} = 0; return; } sub subreport_end { my $self = shift; $self->SUPER::subreport_end( @_ ); $self->print_text( "\n" ); return; } sub table_start { my $self = shift; $self->SUPER::table_start( @_ ); $self->{'curr_headers'} = []; return; } sub table_end { my $self = shift; $self->print_text( " No content in report.\n\n" ) unless ( $self->current_table_entry_count() ); $self->SUPER::table_end( @_ ); # Reset delete $self->{'curr_cols_empty_fmt'}; delete $self->{'curr_cols_print_fmt'}; return; } sub table_info_end { my $self = shift; $self->SUPER::table_info_end( @_ ); return; } #------------------------------------------------------------------------ # Method set_formatters() # # Create the formatter that will be used to print the value of each # column. sub set_formatters { my ( $self ) = @_; my $width = $self->compute_cols_width(); my @cols = $self->current_table_info()->column_infos(); $self->{'curr_cols_empty_fmt'} = []; $self->{'curr_cols_print_fmt'} = []; $self->{'curr_sep'} = ' '; # Empty formatter is only a space specification for (my $i=0; $i<@$width; $i++) { $self->{'curr_cols_empty_fmt'}[$i] = ' ' x $width->[$i]; } # Create a printf specification that can be used # to print a value for each column or when printing an empty foreach my $c ( @cols ) { my $start = $c->col_start(); my $end = $c->col_end(); my $w = 0; for (my $i=$start; $i<=$end; $i++) { $w += $width->[$i]; # Add the sep's space $w++ if $i < $end; } if ( $c->class() eq 'categorical' ) { $self->{'curr_cols_print_fmt'}[$start] = '%-' . $w . 's'; # Create a -- sep for this categorical column on the first row if ( $c->group_info()->row_idx() == 0 ) { $self->{'curr_sep'} .= '-' x $w . ' '; } } else { $self->{'curr_cols_print_fmt'}[$start] = '%' . $w . 's'; # Value column always need generate a sep and reset the # need for one (the next categorical column will generate one) $self->{'curr_sep'} .= '-' x $w; $self->{'curr_sep'} .= ' ' unless $end == @cols -1; } # Sets the col_width in the ColumnInfo object $c->col_width( $w ); } } #------------------------------------------------------------------------ # Method compute_cols_width() # # Determine the width of each columns in the table. Distribute (or crop) # the space difference between the suggested columns width and the # width allocated for formatting (the columns parameter). # # The distribution is allocated based on a 1 character space inserted # between the columns and 2 spaces indenting columns. # # Returns the resulting columns size as an array reference. sub compute_cols_width { my ( $self ) = @_; my $info = $self->current_table_info(); my @cols = $info->column_infos(); my @width = ( 0 x @cols ); my $sep = @cols - 1; my $total = 0; foreach my $c ( @cols ) { $width[ $c->col_start() ] = $c->col_width(); $total += $c->col_width; } my $diff = $self->{'columns'} - ( $total + $sep ) - 2; # '-2' => row indent # Extra/missing space is added/removed to/from categorical # columns # We only select the categorical columns that have columns width # of more than 10 chars my @cat = grep { $_->class() eq 'categorical' && $_->col_width() > 10 } @cols; # None! Grab all then @cat = grep { $_->class() eq 'categorical' } @cols unless @cat; if ($diff > 0 ) { # Allocate evenly between columns my $extra = int( $diff / @cat ); foreach my $c ( @cat ) { $width[ $c->col_start() ] += $extra; } my $rest = $diff % @cat; # Assigned to the first column $width[ $cat[0]->col_start() ] += $rest; } else { $diff = abs $diff; my $found = 0; foreach my $c ( @cat ) { my $w = $width[ $c->col_start() ]; # Reduce columns proportionnally: bigger columns are # reduced more my $shrink = int( $diff * ( $w / $total )); if ( $w - $shrink < 10 ) { # Prevent columns from shrinking too much $shrink = $w - 10; } $width[ $c->col_start() ] -= $shrink; $found += $shrink } $diff = $diff - $found; if ( $diff > 0 ) { # Try to shrink real hard or overflow the table at worst foreach my $c ( sort { $width[$b->col_start() ] <=> $width[ $a->col_start() ] } @cat ) { my $w = $width[ $c->col_start() ]; my $shrink = $w - $diff > 10 ? $diff : $w - 10; $width[ $c->col_start() ] -= $shrink; $diff -= $shrink; last if $diff <= 0; } } } return \@width; } sub handle_header_row { my ( $self, $row ) = @_; my @header_row = (); for (my $i=0; $i<@$row; $i++) { my $c = $row->[$i]; if ( $c ) { $header_row[$i] = { 'content' => $c->label, 'col_info' => $c, }; } else { $header_row[$i] = undef; } } push @{$self->{'curr_headers'}}, \@header_row; return; } sub handle_row { my ( $self, $row ) = @_; if ($self->{'curr_headers'}) { foreach my $r ( @{$self->{'curr_headers'}}) { $self->print_row( $r ); } $self->print_sep; delete $self->{'curr_headers'}; } $self->print_row( $row ); return; } sub handle_table_summary { my ( $self, $nrecords, $row ) = @_; return unless $nrecords && $self->current_table_entry_count(); $row->[0] = { 'content' => "Total for $nrecords records", 'col_info' => $self->current_table_info->column_info_by_col_start( 0 ) }; $self->print_sep; $self->print_row( $row ); $self->print_text( "\n" ); return; } sub handle_description { my ( $self, $docbook ) = @_; $self->print_text( dbk2txt( $docbook, $self->{'columns'} ) ); return; } sub print_sep { my $self = $_[0]; $self->set_formatters() unless exists $self->{'curr_cols_empty_fmt'}; $self->print_text( $self->{'curr_sep'}, "\n" ); return; } sub print_row { my ( $self, $row ) = @_; $self->set_formatters() unless exists $self->{'curr_cols_empty_fmt'}; my @overflow = @$row; # Initial row indent $self->print_text( " " ); for ( my $i=0; $i< @$row; $i++ ) { my $c = $row->[$i]; if ( $c ) { my $len = length $c->{'content'}; my $w = $c->{'col_info'}->col_width(); # Crop to absolute maximum if ( $len > $self->{'max_name_len'} ) { $c->{'content'} = substr $c->{'content'}, 0, $self->{'max_name_len'}; $len = $self->{'max_name_len'}; } # Check if the content is wider than the column's width my $value; if ( $len > $w ) { $value = substr( $c->{'content'}, 0, $w-1) . "\\"; # Keep the cell content for an overflowing row $c->{'content'} = ' ' . substr $c->{'content'}, $w-1; $overflow[$i] = $c; } else { $value = $c->{'content'}; $overflow[$i] = undef; } $self->print_text( sprintf( $self->{'curr_cols_print_fmt'}[$i], $value ) ); # Skip after the column span $i = $c->{'col_info'}->col_end(); } else { $self->print_text( $self->{'curr_cols_empty_fmt'}[$i] ); } $self->print_text( " " ) unless $i + 1 == @$row; } $self->print_text( "\n" ); # Print overflow row if needed $self->print_row( \@overflow ) if grep { defined $_ } @overflow; return; } 1; __END__ =pod =head1 NAME Lire::ReportParser::AsciiWriter - Lire::ReportParser processor that formats the report in ASCII =head1 SYNOPSIS use Lire::ReportParser::AsciiWriter; my $parser = new Lire::ReportParser::AsciiWriter; eval { $parser->parsefile( "report.xml" ) }; print "Parse failed: $@" if $@; =head1 DESCRIPTION This is a Lire::ReportParser processor which will print the Lire XML Report in ASCII on STDOUT. Its constructor takes the following parameters: =over 4 =item columns The number of columsn for which the report should be formatted. Defaults to 80. =item max_name_length The maximum number of characters that will be kept in name element. Defaults to 180. =item userlevel In description, the maximum level of elements that will be displayed. Defaults to C (i.e. C elements aren't formatted. =back =head1 SEE ALSO Lire::ReportParser(3pm) Lire::AsciiDocBookFormatter(3pm) =head1 VERSION $Id: AsciiWriter.pm,v 1.41 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/ReportParser/ExcelWriter.pm0000644000175000017500000003670710460673257017052 00000000000000package Lire::ReportParser::ExcelWriter; use strict; use vars qw/ $DATE_SYSTEM @name_cols_width/; use base qw/ Lire::ReportParser::RowColHandler /; use Lire::ReportParser::AsciiDocBookFormatter qw/dbk2txt/; use POSIX qw/ceil/; use Spreadsheet::WriteExcel; #use Time::Timezone; use constant MAX_EXCEL_STRING => 255; use constant MAX_SHEET_STRING => 31; use constant DEFAULT_ROW_HEIGHT => 12.75; # Those values are in Excel Points #use constant CHAR_WIDTH => 5.3; #use constant DEFAULT_CELL_WIDTH => 48; #use constant MAX_CELL_WIDTH => 4 * 48; # Spreadsheet::WriteExcel seems to work with characters use constant CHAR_WIDTH => 1; use constant DEFAULT_CELL_WIDTH => 9; use constant MAX_CELL_WIDTH => 36; BEGIN { # Use 1900 date system on all platforms other than Apple Mac (for which # use 1904 date system). $DATE_SYSTEM = ($^O eq 'MacOS') ? 1 : 0; } # # This was inspired by the comments and programs datecalc1.pl # included in Spreadsheet::WriteExcel and is # Copyright (c) 2000, Andrew Benham. # This program is free software. It may be used, redistributed and/or # modified under the same terms as Perl itself. # # It was modified to use Time::Timezone which is included in Lire. # sub epoch2excel_date { my ($time) = @_; # Divide timestamp by number of seconds in a day. # This gives a date serial with '0' on 1 Jan 1970. my $serial = $time / 86400; # Adjust the date serial by the offset appropriate to the # currently selected system (1900/1904). if ($DATE_SYSTEM == 0) { # use 1900 system $serial += 25569; } else { # use 1904 system $serial += 24107; } # Actually, this gives the wrong date. Maybe this is specific to # gnumeric and OpenOffice on UNIX. # The correct date appears if we don't correct the value for time zone. # # Fix for timezone # my $offset = tz_local_offset( $time ); # $serial += $offset / 8640; # Perpetuate the error that 1900 was a leap year by decrementing # the serial if we're using the 1900 system and the date is prior to # 1 Mar 1900. This has the effect of making serial value '60' # 29 Feb 1900. # This fix only has any effect if UNIX/Perl time on the platform # can represent 1900. Many can't. unless ($DATE_SYSTEM) { $serial-- if ($serial < 61); # '61' is 1 Mar 1900 } return $serial; } sub new { my ( $self, %args ) = @_; $self = $self->SUPER::new( %args, 'summary_when' => 'after', ); $self->{'_output_file'} = $args{'output_file'} || '-', return $self; } sub report_start { my $self = shift; $self->SUPER::report_start( @_ ); $self->{'report_date'} = undef; $self->{'report_timespan'} = undef; $self->{'workbook'} = new Spreadsheet::WriteExcel($self->{'_output_file'}); # Create some format that we are going to use $self->{'title_fmt'} = $self->{'workbook'}->addformat( 'size' => 18, 'bold' => 1, ); $self->{'date_fmt'} = $self->{'workbook'}->addformat( 'num_format' => "yyyy/mm/dd", 'align' => "left", 'valign' => "top", ); $self->{'timestamp_fmt'} = $self->{'workbook'}->addformat( 'num_format' => "yyyy/mm/dd hh:mm:ss", 'align' => "left", 'valign' => "top", ); $self->{'datetime_fmt'} = $self->{'workbook'}->addformat( 'num_format' => "yyyy/mm/dd hh:mm", 'align' => "left", 'valign' => "top", ); $self->{'time_fmt'} = $self->{'workbook'}->addformat( 'num_format' => "hh:mm", 'align' => "left", 'valign' => "top", ); $self->{'name_fmt'} = $self->{'workbook'}->addformat( 'num_format' => 0x31, # Builtin: @ 'align' => "justify", 'valign' => "top", ); $self->{'label_fmt'} = $self->{'workbook'}->addformat( 'num_format' => 0x31, # Builtin: @ 'align' => "left", 'valign' => "left", 'bold' => 1, 'size' => 12, ); $self->{'header_fmt'} = $self->{'workbook'}->addformat( 'num_format' => 0x31, # Builtin: @ 'align' => "left", 'valign' => "left", 'bold' => 1, ); $self->{'description_fmt'} = $self->{'workbook'}->addformat( 'num_format' => 0x31, # Builtin: @ 'align' => "left", 'valign' => "left", ); $self->{'value_fmt'} = $self->{'workbook'}->addformat( 'num_format' => 0x00, # Builtin: General 'align' => "right", 'valign' => "top", ); } sub report_end { my $self = shift; $self->SUPER::report_end( @_ ); # Activate the first sheet my $first = ($self->{'workbook'}->sheets)[0]; if ( $first ) { $first->set_first_sheet(); $first->activate(); } $self->{'workbook'}->close(); return; } sub section_end { my $self = shift; $self->{'curr_section'}->write( $self->{'curr_row'}++, 0, "No subreports were generated for this section.", $self->{'label_fmt'}, ) if ( ! $self->current_section_subreport_count() ); $self->SUPER::section_end( @_ ); return; } sub handle_title { my ( $self, $title ) = @_; # Trim the title $title =~ s/^\s*//; $title =~ s/\s*$//; if ($self->in_element( "lire:section" ) ) { # Section's title my $title = substr( $title, 0, MAX_SHEET_STRING ); my $first_sheet = ! $self->{'workbook'}->sheets; # Create a new worksheet $self->{'curr_section'} = $self->{'workbook'}->addworksheet( $title ); $self->{'curr_row'} = 0; $self->{'curr_cols_width'} = []; if ( $first_sheet ) { # Put "header" information on first sheet my @labels = ( "Report generated", "Log file started", "Log file ended" ); my @dates = ( $self->{'report_date'}, @{$self->{'report_timespan'}} ); for (my $i=0; $i<@labels; $i++) { my $date = epoch2excel_date( $dates[$i] ); $self->{'curr_section'}->write( $i, 0, $labels[$i], $self->{'label_fmt'}, ); $self->{'curr_section'}->write( $i, 1, $date, $self->{'timestamp_fmt'}, ); $self->{'curr_section'}->set_row( $i, 14 ); } $self->{'curr_row'} = @labels + 1; my $width = length("yyyy/mm/dd hh:mm:ss") * CHAR_WIDTH; $self->{'curr_cols_width'}[1] = $width; $self->{'curr_section'}->set_column( 1, 1, $width ); } } else { # Subreport's title my $title = substr( $title, 0, MAX_EXCEL_STRING ); $self->{'curr_section'}->set_row( $self->{'curr_row'}, 22 ); $self->{'curr_section'}->write( $self->{'curr_row'}++, 0, $title, $self->{'title_fmt'}, ); } return; } sub handle_description { my ( $self, $docbook ) = @_; my $desc = dbk2txt( $docbook ); # Put each line in a separate cell foreach my $line ( split /\n/, $desc ) { if ( defined $line ) { # Trim spaces $line =~ s/^\s+//; $line =~ s/\s+$//; $self->{'curr_section'}->write( $self->{'curr_row'}, 0, $line, $self->{'description_fmt'}, ); } $self->{'curr_row'}++; } # Skip one row after the description $self->{'curr_row'}++; return; } sub handle_date { my ( $self, $date, $time ) = @_; $self->{'report_date'} = $time unless defined $self->{'report_date'}; return; } sub handle_timespan { my ( $self, $timespan, $start, $end ) = @_; $self->{'report_timespan'} = [$start, $end] unless defined $self->{'report_timespan'}; return; } sub subreport_end { my $self = shift; $self->SUPER::subreport_end( @_ ); # Leave one extra empty row $self->{'curr_row'} += 2; return; } sub table_start { my $self = shift; $self->SUPER::table_start( @_ ); $self->{'curr_headers'} = []; return; } sub table_end { my $self = shift; # Skip one row $self->{'curr_row'}++; $self->{'curr_section'}->write( $self->{'curr_row'}++, 0, "No content in report.", $self->{'label_fmt'} ) if ! $self->current_table_entry_count(); $self->SUPER::table_end( @_ ); return; } sub table_info_end { my $self = shift; $self->SUPER::table_info_end( @_ ); # Upgrade the column's width of the sheet based # on the suggested column's width my $table_info = $self->current_table_info(); my @cols = $table_info->column_infos(); foreach my $col ( @cols ) { my $i = $col->col_start; my $curr_width = $self->{'curr_cols_width'}[$i] || DEFAULT_CELL_WIDTH; my $width = $col->col_width * CHAR_WIDTH; $width = MAX_CELL_WIDTH if $width > MAX_CELL_WIDTH; if ( $width > $curr_width ) { $self->{'curr_cols_width'}[$i] = $width; $self->{'curr_section'}->set_column( $i, $i, $width ); } } return; } sub handle_header_row { my ( $self, $row ) = @_; push @{$self->{'curr_headers'}}, $row; return; } sub write_header_rows { my $self = $_[0]; foreach my $row ( @{$self->{'curr_headers'}} ) { $self->{'curr_row'}++; $self->{'curr_row_height'} = DEFAULT_ROW_HEIGHT; foreach my $c ( @$row ) { next unless defined $c; my $s = substr $c->label, 0, MAX_EXCEL_STRING; $self->{'curr_section'}->write( $self->{'curr_row'}, $c->col_start, $s, $self->{'header_fmt'} ); } } return; } sub handle_row { my ( $self, $row ) = @_; if ( $self->{'curr_headers'} ) { $self->write_header_rows; delete $self->{'curr_headers'}; } $self->{'curr_row'}++; $self->{'curr_row_height'} = DEFAULT_ROW_HEIGHT; foreach my $c ( @$row ) { next unless defined $c; if ($c->{'col_info'}->class eq 'categorical' ) { $self->write_categorical_cell( $c ); } else { $self->write_value_cell( $c ); } } return; } sub handle_table_summary { my ( $self, $nrecords, $row ) = @_; return unless $nrecords && $self->current_table_entry_count(); $self->{'curr_row_height'} = DEFAULT_ROW_HEIGHT; # Write the summary cell $self->{'curr_section'}->write( $self->{'curr_row'}, 0, "Total", $self->{'header_fmt'}, ); foreach my $c ( @$row ) { next unless defined $c; $self->write_value_cell( $c ); } # We increase it only after because it was already increased # in table_end $self->{'curr_row'}++; return; } sub write_categorical_cell { my ( $self, $name ) = @_; my $s = substr $name->{'content'}, 0, MAX_EXCEL_STRING; my $fmt = $self->{'name_fmt'}; # Convert time classes to their Excel representation if ( $name->{'value'} =~ /^\d+$/ && $name->{'content'} !~ /^(\[|Week)/ && #! Skip Week and rangegroup defined $name->{'range'} && $name->{'range'} =~ /^\d+$/ ) { $s = epoch2excel_date( $name->{'value'} ); if ( $name->{'range'} < 86400 ) { $fmt = $self->{'datetime_fmt'}; } else { $fmt = $self->{'date_fmt'}; } } my $col = $name->{'col_info'}->col_start; my $len = length $s; # Enlarge the row's height i if ( $len * CHAR_WIDTH > MAX_CELL_WIDTH ) { my $row = ceil( $len * CHAR_WIDTH / MAX_CELL_WIDTH ); my $height = $row * DEFAULT_ROW_HEIGHT; if ( $height > $self->{'curr_row_height'} ) { $self->{'curr_section'}->set_row( $self->{'curr_row'}, $height, ); $self->{'curr_row_height'} = $height; } } # Write it $self->{'curr_section'}->write( $self->{'curr_row'}, $col, $s, $fmt ); return; } sub write_value_cell { my ( $self, $value ) = @_; $self->{'curr_section'}->write( $self->{'curr_row'}, $value->{'col_info'}->col_start, $value->{'content'}, $self->{'value_fmt'} ); return; } 1; __END__ =pod =head1 NAME Lire::ReportParser::ExcelWriter - Transform Lire XML Reports into a Excel95(tm) spreadsheet. =head1 SYNOPSIS use Lire::ReportParser::ExceltWriter; my $parser = new Lire::ReportParser::ExcelWriter(); eval { $parser->parsefile( "report.xml" ) }; print "Parse failed: $@" if $@; =head1 DESCRIPTION This is a Lire::ReportParser processor which will transform the Lire XML report into a Excel95(tm) spreadsheet which will be output on STDOUT. Its constructor doesn't take any parameters. =head1 SEE ALSO Lire::ReportParser(3pm) Spreadsheet::WriteExcel(3pm) =head1 VERSION $Id: ExcelWriter.pm,v 1.19 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/ReportParser/LaTeXDocBookFormatter.pm0000644000175000017500000003302410460673257020704 00000000000000package Lire::ReportParser::LaTeXDocBookFormatter; use strict; use base qw/ Exporter Lire::DocBookParser /; use Lire::Utils qw/deep_copy/; use Lire::I18N qw/ensure_utf8/; our @EXPORT_OK = qw/ dbk2latex /; =pod =head1 NAME Lire::ReportParser::LaTeXDocBookFormatter - Lire::DocBookParser subclass which formats description to LaTeX. =head1 SYNOPSIS To convert a DocBook decription to LaTeX: use Lire::ReportParser::LaTeXDocBookFormatter qw/dbk2latex/; my $LaTeX = dbk2latex( "Test" ); =head1 DESCRIPTION This package implements methods that can handle the content of C elements and it can be used by a subclass of Lire::ReportParser. Client only have to inherit from this module so that a handle_description() method is available to process the text formatted DocBook description. This module also provide a convenient dbk2txt() function which can be used to format a string containing DocBook elements into an ASCII equivalent. =head1 USING Lire::ReportParser::LaTeXDocBookFormatter Lire::ReportParser processors that would like to work with text version of the description should inherit from Lire::ReportParser::LaTeXDocBookFormatter in addition to Lire::ReportParser. If they override the description_start(), description_end()methods, they B link to their parents' version using C. Additionnally, they should merge the value elements_spec() in their elements_spec() implementation. The Lire::ReportParser::LaTeXDocBookFormatter should be listed before Lire::ReportParser in the @ISA. The LaTeXDocBookFormatter doesn't inherit directly from Lire::ReportParser so that it can be used in multiple inheritance scenario. =cut sub new { my $self = shift->SUPER::new( @_ ); return $self; } =pod =head2 dbk_start_processing() Initializes the parser's structure for formatting DocBook XML as ASCII. This is used from the description_start implementation. =cut sub dbk_start_processing { my $self = $_[0]; $self->{'dbk_process'} = 1; $self->init_stack( 'latex' ); $self->stack_push( 'latex', Lire::LaTeX::Node->new() ); return; } =pod =head2 dbk_end_processing() Cleans the parser structure. This is used from the description_end() implementation. =cut sub dbk_end_processing { my $self = $_[0]; delete $self->{'dbk_process'}; die "stack 'latex' should be empty" unless $self->is_stack_empty( 'latex' ); return; } sub namespaces { my $self = $_[0]; return { "http://www.logreport.org/LRML/" => 'lire' }; } sub elements_spec { my $self = $_[0]; my $spec = deep_copy( $self->Lire::DocBookParser::elements_spec() ); foreach my $element ( keys %$spec ) { $spec->{$element}{'start'} = 'latex_start'; $spec->{$element}{'end'} = 'latex_end'; $spec->{$element}{'char'} = 'latex_char' if exists $spec->{$element}{'char'}; } $spec->{'lire:description'} = [ @Lire::DocBookParser::top_levels ]; return $spec; } sub description_start { $_[0]->dbk_start_processing(); return; } sub description_end { my $self = $_[0]; return unless $self->{'dbk_process'}; my $root = $self->stack_pop( 'latex' ); $self->handle_description( $root->as_string() ); $self->dbk_end_processing(); return; } =pod =head2 handle_description( $description ) This method is invoked after the closing tag of the C element is encountered. The $description contains the description converter to LaTeX. =cut sub handle_description { $_[0]{'saved_latex'} = $_[1]; return; } sub parse_end { return $_[0]{'saved_latex'}; } my %dbk2latex = ( 'para' => 'Para', 'emphasis' => 'Emph', 'foreignphrase' => 'Emph', 'ulink' => 'Href', 'email' => 'Email', 'superscript' => 'Superscript', 'subscript' => 'Subscript', 'optional' => 'Slanted', 'parameter' => 'Slanted', 'varname' => 'Slanted', 'command' => 'TextTT', 'constant' => 'TextTT', 'computeroutput' => 'TextTT', 'filename' => 'TextTT', 'userinput' => 'TextTT', 'quote' => 'Quote', 'itemizedlist' => 'List', 'orderedlist' => 'List', 'variablelist' => 'List', 'listitem' => 'Item', 'varlistentry' => 'NamedItem', 'term' => 'Term', 'title' => 'Title', 'warning' => 'Admonition', 'caution' => 'Admonition', 'important' => 'Admonition', 'note' => 'Admonition', 'tip' => 'Admonition', ); sub latex_start { my ( $self, $name, $attr ) = @_; my $class = "Lire::LaTeX::" . ( $dbk2latex{$name} || 'Node' ); my $node = $class->new( $name, $attr ); $self->stack_peek( 'latex' )->add_child( $node ); $self->stack_push( 'latex', $node ); return; } sub latex_end { my ( $self, $name ) = @_; $self->stack_pop( 'latex' ); return; } sub latex_char { my ( $self, $text ) = @_; $self->stack_peek( 'latex' )->add_child( Lire::LaTeX::Text->new( $text ) ); return; } =pod =head1 PROCESSING LaTeX DESCRIPTION The generate LaTeX is encoded in UTF-8, so Omega must be used to process it. Additionnally, the result of calling dbk_latex_environment() should be added to the document preambule. It adds some environment and command definitions used by the formatter. =head1 FORMATTING DocBook STRINGS If you have DocBook content in a string, like you can obtain from some of the Report Specifications object, you can convert it to LaTeX by using the dbx2latex() function. =cut sub dbk_latex_environment { return <<'EOF'; EOF } =pod =head2 dbk2txt( $docbook_str, [$columns] ) Returns a plain text version of the DocBook XML fragment $docbook_str. The C parameter sets the number of columns in which the DocBook text should be formatted. This method will die() in case of error. =cut sub dbk2latex { my $docbook_str = $_[0]; my $parser = new Lire::ReportParser::LaTeXDocBookFormatter(); return $parser->parse( '' . '' . ensure_utf8( $docbook_str ) . '' ); } package Lire::LaTeX::Node; sub new { return bless { 'children' => [] }, shift; } sub add_child { my ( $self, $child ) = @_; push @{$self->{'children'}}, $child; return; } sub as_string { my $self = $_[0]; my $str = ''; foreach my $child ( @{$self->{'children'}} ) { $str .= $child->as_string(); } return $str; } package Lire::LaTeX::Displayed; use base qw/Lire::LaTeX::Node/; package Lire::LaTeX::Inlined; use base qw/Lire::LaTeX::Node/; package Lire::LaTeX::Para; use base qw/Lire::LaTeX::Displayed/; use Text::Wrap; sub as_string { my $self = $_[0]; local $Text::Wrap::columns = 72; my $str = ''; my $run = ''; foreach my $child ( @{$self->{'children'}} ) { if ( $child->isa( 'Lire::LaTeX::Displayed' ) ) { $str .= $self->wrap_run( $run, length $str ); $str .= $child->as_string(); $run = ''; } else { $run .= $child->as_string(); } } $str .= $self->wrap_run( $run, length $str ); return $str; } sub wrap_run { my ( $self, $run, $noindent ) = @_; return '' unless length $run; $run =~ s/\s+/ /g; return ( $noindent ? "\\noindent\n" : '' ) . wrap( '', '', $run ) . "\n\n"; } package Lire::LaTeX::Emph; use base qw/Lire::LaTeX::Inlined/; sub as_string { return '\emph{' . shift->SUPER::as_string() . '}'; } package Lire::LaTeX::Slanted; use base qw/Lire::LaTeX::Inlined/; sub as_string { return '\textsl{' . shift->SUPER::as_string() . '}'; } package Lire::LaTeX::TextTT; use base qw/Lire::LaTeX::Inlined/; sub as_string { return '\texttt{' . shift->SUPER::as_string() . '}'; } package Lire::LaTeX::Subscript; use base qw/Lire::LaTeX::Inlined/; sub as_string { return '\raisebox{-1ex}{' . shift->SUPER::as_string() . '}'; } package Lire::LaTeX::Superscript; use base qw/Lire::LaTeX::Inlined/; sub as_string { return '\raisebox{1ex}{' . shift->SUPER::as_string() . '}'; } package Lire::LaTeX::Quote; use base qw/Lire::LaTeX::Inlined/; sub as_string { return '``' . shift->SUPER::as_string() . "''"; } package Lire::LaTeX::Href; use base qw/Lire::LaTeX::Inlined/; sub new { my ( $class, $name, $attr ) = @_; my $self = $class->SUPER::new( $attr ); $self->{'href'} = $attr->{'url'}; return $self; } sub as_string { my $self = $_[0]; return '\href{' . $self->{'href'} . '}{' . $self->SUPER::as_string() . '}'; } package Lire::LaTeX::Email; use base qw/Lire::LaTeX::Inlined/; sub as_string { my $self = $_[0]; my $email = $self->SUPER::as_string(); return "\\href{mailto:$email}{$email}"; } package Lire::LaTeX::Text; use base qw/Lire::LaTeX::Inlined/; use Lire::Utils qw/latex_encode/; sub new { my ( $pkg, $content ) = @_; return bless \$content, $pkg; } sub as_string { my $self = $_[0]; return latex_encode( $$self ); } package Lire::LaTeX::Admonition; use base qw/Lire::LaTeX::Displayed/; use Locale::TextDomain 'lire'; my %admonition_titles = ( 'note' => N__( 'Note:' ), 'warning' => N__( 'Warning:' ), 'tip' => N__( 'Tip:' ), 'caution' => N__( 'Caution:' ), 'important' => N__( 'Important:' ), ); sub new { my ( $class, $name, $attr ) = @_; my $self = $class->SUPER::new(); $self->{'title'} = Lire::LaTeX::Title->new(); $self->{'title'}->add_child( Lire::LaTeX::Text->new( $__{$admonition_titles{$name}} ) ); return $self; } sub add_child { my ( $self, $child ) = @_; if ( $child->isa( 'Lire::LaTeX::Title' ) ) { $self->{'title'} = $child; } else { $self->SUPER::add_child( $child ); } } sub as_string { my $self = $_[0]; return join( "", "\\begin{quote}\n", $self->{'title'}->as_string(), "\n", $self->SUPER::as_string(), "\\end{quote}\n\n" ); } package Lire::LaTeX::List; use base qw/Lire::LaTeX::Displayed/; my %dbk2latex_list = ( 'itemizedlist' => 'itemize', 'orderedlist' => 'enumerate', 'variablelist' => 'description', ); sub new { my ( $class, $name, $attr ) = @_; my $self = bless { 'title' => undef, 'preamble' => [], 'type' => $dbk2latex_list{$name}, 'items' => [] }, $class; return $self; } sub add_child { my ( $self, $child ) = @_; if ( $child->isa( 'Lire::LaTeX::Title' ) ) { $self->{'title'} = $child; } elsif ( $child->isa( 'Lire::LaTeX::Item' ) ) { push @{$self->{'items'}}, $child; } else { push @{$self->{'preamble'}}, $child; } } sub as_string { my $self = $_[0]; my $str = ''; if ( $self->{'title'} ) { $str .= $self->{'title'}->as_string() . "\n\n\\nopagebreak[3]\n\n"; } if ( @{$self->{'preamble'}} ) { $str .= join( "", ( map { $_->as_string() } @{$self->{'preamble'}} ), "\\nopagebreak[2]\n\n" ); } $str .= join ( "", "\\begin{$self->{'type'}}\n", ( map { $_->as_string() } @{$self->{'items'}} ), "\\end{$self->{'type'}}\n\n" ); return $str; } package Lire::LaTeX::Title; use base qw/Lire::LaTeX::Inlined/; sub as_string { return '\large{\textbf{' . shift->SUPER::as_string() . '}}'; } package Lire::LaTeX::Item; use base qw/Lire::LaTeX::Inlined/; sub as_string { return '\item ' . shift->SUPER::as_string(); } package Lire::LaTeX::NamedItem; use base qw/Lire::LaTeX::Item/; sub new { return bless { 'term' => undef, 'def' => undef }, shift; } sub add_child { my ( $self, $child ) = @_; if ( $child->isa( 'Lire::LaTeX::Term' ) ) { $self->{'term'} = $child; } else { $self->{'def'} = $child; } } sub as_string { my $self = $_[0]; return $self->{'term'}->as_string() . ' ' . $self->{'def'}->Lire::LaTeX::Node::as_string(); } package Lire::LaTeX::Term; use base qw/Lire::LaTeX::Inlined/; sub as_string { return '\item[' . shift->SUPER::as_string() . ']'; } 1; __END__ =head1 SEE ALSO Lire::ReportParser(3pm) =head1 VERSION $Id: LaTeXDocBookFormatter.pm,v 1.4 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/ReportParser/ReportBuilder.pm0000644000175000017500000002205510460673257017366 00000000000000package Lire::ReportParser::ReportBuilder; use strict; use base qw/ Lire::ReportParser /; use Lire::Report; use Lire::Report::Section; use Lire::Report::Subreport; use Lire::Utils qw/ check_param /; use Lire::ReportSpec; sub parse_start { my $self = $_[0]; $self->{'curr_section'} = undef; $self->{'curr_subreport'} = undef; return; } sub parse_end { my $self = $_[0]; return $self->{'report'}; } sub parse_with_images { my ( $self, $fh, $images_dir ) = @_; check_param( $fh, 'fh' ); check_param( $images_dir, 'images_dir' ); return $self->parse( $fh ); } sub parsefile_with_images { my ( $self, $file, $images_dir ) = @_; check_param( $file, 'file' ); check_param( $images_dir, 'images_dir' ); return $self->parsefile( $file ); } sub report_start { my ( $self, $name, $attr ) = @_; $self->SUPER::report_start( $name, $attr ); $self->{'report'} = new Lire::Report(); $self->{'report'}->generator( __PACKAGE__ . "(3pm)" ); return; } sub handle_title { my ( $self, $title ) = @_; if ( $self->{'curr_subreport'} ) { $self->{'curr_subreport'}->title( $title ); } elsif ( $self->{'curr_section'} ) { $self->{'curr_section'}->title( $title ); } else { $self->{'report'}->title( $title ); } return; } sub handle_date { my ( $self, $date, $date_epoch ) = @_; $self->{'report'}->date( $date_epoch ); return; } sub handle_timespan { my ( $self, $timespan, $start, $end, $period ) = @_; $self->{'report'}->timespan_period( $period ) if defined $period; $self->{'report'}->timespan_start( $start ); $self->{'report'}->timespan_end( $end ); return; } sub handle_description { my ( $self, $desc )= @_; my $o; if ( $self->{'curr_subreport'} ) { $o = $self->{'curr_subreport'}; } elsif ( $self->{'curr_section'} ) { $o = $self->{'curr_section'}; } else { $o = $self->{'report'}; } $o->description( $desc ); return; } sub section_start { my ( $self, $name, $attr ) = @_; $self->SUPER::section_start( $name, $attr ); $self->{'curr_section'} = new Lire::Report::Section(); $self->{'report'}->add_section( $self->{'curr_section'} ); return; } sub section_end { my ( $self, $name ) = @_; $self->SUPER::section_end( $name ); $self->{'curr_section'} = undef; return; } sub subreport_start { my ( $self, $name, $attr ) = @_; $self->SUPER::subreport_start( $name, $attr ); my $subreport = new Lire::Report::Subreport( $attr->{'superservice'}, $attr->{'type'} ); $attr->{'id'} = $self->{'report'}->create_subreport_id( $attr->{'type'} ) unless defined $attr->{'id'}; $subreport->id( $attr->{'id'} ); $subreport->schemas( split /\s+/, $attr->{'schemas'} ) if $attr->{'schemas'}; $self->{'curr_subreport'} = $subreport; $self->{'curr_section'}->add_subreport( $self->{'curr_subreport'} ); $self->init_stack( 'group' ); $self->init_stack( 'entry' ); $self->stack_push( 'group', $subreport ); return; } sub subreport_end { my ( $self, $name ) = @_; $self->SUPER::subreport_end( $name ); $self->{'curr_subreport'} = undef; $self->stack_pop( 'group' ); $self->error( "subreport_end(): assertion failed: stack 'group' should be empty" ) unless $self->is_stack_empty( 'group' ); $self->error( "subreport_end(): assertion failed: stack 'entry' should be empty" ) unless $self->is_stack_empty( 'entry' ); return; } sub missing_subreport_start { my ( $self, $name, $attr ) = @_; $self->SUPER::missing_subreport_start( $name, $attr ); my $subreport = new_missing Lire::Report::Subreport( $attr->{'superservice'}, $attr->{'type'}, $attr->{'reason'} ); $attr->{'id'} = $self->{'report'}->create_subreport_id( $attr->{'type'} ) unless defined $attr->{'id'}; $subreport->id( $attr->{'id'} ); $subreport->schemas( split /\s+/, $attr->{'schemas'} ) if $attr->{'schemas'}; $self->{'curr_section'}->add_subreport( $subreport ); return; } sub table_start { my ( $self, $name, $attr ) = @_; $self->SUPER::table_start( $name, $attr ); $self->{'curr_charttype'} = $attr->{'charttype'}; $self->{'curr_subreport'}->show( $attr->{'show'} ); return; } sub group_summary_start { my ( $self, $name, $attr ) = @_; $self->SUPER::group_summary_start( $name, $attr ); my $curr_group = $self->stack_peek( 'group' ); $curr_group->nrecords( $attr->{'nrecords'} ); $curr_group->missing_cases( $attr->{'missing-cases'} ); $curr_group->row_idx( $attr->{'row-idx'} ) if defined $attr->{'row-idx'}; return; } sub group_start { my ( $self, $name, $attr ) = @_; $self->SUPER::group_start( $name, $attr ); my $curr_entry = $self->stack_peek( 'entry' ); my $group = $curr_entry->create_group(); $group->show( $attr->{'show'} ) if defined $attr->{'show'}; $self->stack_push( 'group', $group ); return; } sub group_end { my ( $self, $name ) = @_; $self->SUPER::group_end( $name ); $self->stack_pop( 'group' ); return; } sub table_info_end { my ( $self, $name ) = @_; $self->SUPER::table_info_end( $name ); $self->{'curr_subreport'}->table_info( $self->current_table_info() ); if ( $self->{'curr_charttype'} ) { my $cfg = Lire::ReportSpec::charttype2chart_config( $self->{'curr_charttype'}, $self->{'curr_subreport'}->id(), $self->current_table_info() ); $self->{'curr_subreport'}->add_chart_config( $cfg ); delete $self->{'curr_charttype'}; } return; } sub entry_start { my ( $self, $name, $attr ) = @_; $self->SUPER::entry_start( $name, $attr ); my $entry = $self->stack_peek( 'group' )->create_entry(); $entry->row_idx( $attr->{'row-idx'} ) if defined $attr->{'row-idx'}; $self->stack_push( 'entry', $entry ); return; } sub entry_end { my ( $self, $name ) = @_; $self->SUPER::entry_end( $name ); $self->stack_pop( 'entry' ); return; } sub handle_name { my ( $self, $name ) = @_; $self->stack_peek( 'entry' )->add_name( $name->{'content'}, $name->{'value'}, $name->{'range'} ); return; } sub handle_value { my ( $self, $value ) = @_; $self->stack_peek( 'entry' )->add_value( 'content' => $value->{'content'}, 'value' => $value->{'value'}, 'total' => $value->{'total'}, 'n' => $value->{'n'}, 'missing_cases' => $value->{'missing-cases'} ); return; } sub handle_summary_value { my ( $self, $value ) = @_; $self->stack_peek( 'group' )->set_summary_value( $value->{'col_info'}->name(), 'content' => $value->{'content'}, 'value' => $value->{'value'}, 'total' =>$value->{'total'}, 'n' => $value->{'n'}, 'missing_cases' => $value->{'missing-cases'} ); return; } sub handle_chart_configs { my ( $self, $configs ) = @_; foreach my $cfg ( @$configs ) { $self->{'curr_subreport'}->add_chart_config( $cfg ); } return; } 1; __END__ =pod =head1 NAME Lire::ReportParser::ReportBuilder - Creates Lire::Report objects from XML files =head1 SYNOPSIS use Lire::ReportParser::ReportBuilder; my $parser = new Lire::ReportParser::ReportBuilder; my $report = $parser->parsefile( "report.xml" ); =head1 DESCRIPTION This is a subclass of Lire::ReportParser that creates an object representation of a Lire report contained in a XML file. =head1 SEE ALSO Lire::Report(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: ReportBuilder.pm,v 1.41 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/ReportParser/HTMLDocBookFormatter.pm0000644000175000017500000003534310460673257020501 00000000000000package Lire::ReportParser::HTMLDocBookFormatter; use strict; use base qw/ Exporter Lire::DocBookParser /; use Text::Wrap qw/ wrap /; use Lire::Utils qw/deep_copy/; use Lire::I18N qw/ensure_utf8/; our @EXPORT_OK = qw/ dbk2html /; our %dbk2html = ( 'quote' => 'q', 'abbrev' => 'abbr', 'acronym' => 'acronym', 'computeroutput' => 'samp', 'prompt' => 'samp', 'emphasis' => 'em', 'userinput' => 'kbd', 'subscript' => 'sub', 'superscript' => 'sup' ); our @dbk_vartags = qw/ varname envar constant structfield structname function option optional parameter classname symbol property type errorname /; =pod =head1 NAME Lire::ReportParser::HTMLDocBookFormatter - Lire::ReportParser subclass which formats description. =head1 SYNOPSIS To format DocBook: use Lire::ReportParser::HTMLDocBookFormatter qw/dbk2html/; my $txt = dbk2html( "Test" ); In XML Report processors : package MyParser; use base qw/ Lire::ReportParser::HTMLDocBookFormatter Lire::ReportParser /; sub new { my $self = shift->SUPER::new( @_ ); $self->init_docbook_formatter( @_ ); return $self; } sub handle_description { my ( $self, $desc ) = @_; print $desc; return; } =head1 DESCRIPTION Lire::ReportParser::HTMLDocBookFormatter is the counterpart to Lire::ReportParser::AsciiDocBookFormatter for the HTML output format. Please read its documentation to learn how to use this class. Their use is exactly the same. =cut sub new { my $self = shift->SUPER::new( @_ ); $self->init_docbook_formatter( @_ ); return $self; } sub namespaces { my $self = $_[0]; return { "http://www.logreport.org/LRML/" => 'lire' }; } sub elements_spec { my $self = $_[0]; my $spec = deep_copy( $self->Lire::DocBookParser::elements_spec() ); foreach my $admon ( @Lire::DocBookParser::admonitions_mix ) { $spec->{$admon}{'start'} = 'admonition_start'; $spec->{$admon}{'end'} = 'admonition_end'; } foreach my $element ( keys %dbk2html ) { $spec->{$element}{'start'} = 'mapped_start'; $spec->{$element}{'end'} = 'mapped_end'; } foreach my $element ( @dbk_vartags ) { $spec->{$element}{'start'} = 'var_start'; $spec->{$element}{'end'} = 'var_end'; } my %except = map { $_ => 1 } ( keys %dbk2html, @dbk_vartags, 'email', 'term', 'title', 'ulink' ); foreach my $element ( @Lire::DocBookParser::inline_mix ) { next if $except{$element}; $spec->{$element}{'start'} = 'span_start'; $spec->{$element}{'end'} = 'span_end'; } foreach my $element ( keys %$spec ) { next if $element eq 'ulink'; $spec->{$element}{'char'} = 'inline_char' if exists $spec->{$element}{'char'}; } $spec->{'email'}{'start'} = 'collector_start'; $spec->{'email'}{'char'} = 'collector_char'; $spec->{'term'}{'char'} = 'collector_char'; $spec->{'lire:description'} = [ @Lire::DocBookParser::top_levels ]; return $spec; } sub init_docbook_formatter { my ( $self, %args ) = @_; $self->{'dbk_columns'} = $args{'dbk_columns'} || 78; $self->{'dbk_tag_ender'} = ( $args{'xhtml'} ? ' /' : '' ); return $self; } sub dbk_start_processing { my $self = $_[0]; $self->{'dbk_process'} = 1; $self->{'dbk_text'} = ""; $self->{'dbk_text_blocks'} = []; $self->{'dbk_lists'} = []; $self->{'dbk_left_margin'} = 4; return; } sub dbk_end_processing { my ( $self ) = @_; delete $self->{'dbk_process'}; delete $self->{'dbk_text'}; delete $self->{'dbk_text_blocks'}; delete $self->{'dbk_lists'}; return; } sub description_start { $_[0]->dbk_start_processing(); return; } sub description_end { my ( $self ) = @_; return unless $self->{'dbk_process'}; $self->handle_description( $self->{'dbk_text'} ); $self->dbk_end_processing(); return; } sub handle_description { $_[0]{'saved_dbk'} = $_[1]; return; } sub parse_end { return $_[0]{'saved_dbk'}; } sub parent_block { return undef unless @{$_[0]{'dbk_text_blocks'}} > 1; return $_[0]{'dbk_text_blocks'}[$#{$_[0]{'dbk_text_blocks'}} - 1]; } sub current_block { return undef unless @{$_[0]{'dbk_text_blocks'}}; return $_[0]{'dbk_text_blocks'}[$#{$_[0]{'dbk_text_blocks'}}]; } sub print_block { my ( $self ) = @_; my $block = $self->current_block(); return unless $block; return unless length $block->{'dbk_text'}; my $margin = ' ' x $self->{'dbk_left_margin'}; my $initial = $margin . $block->{'dbk_initial_indent'}; my $next = $margin . $block->{'dbk_indent'}; # Squash space and trim the string. $block->{'dbk_text'} =~ tr/\n\t / /s; $block->{'dbk_text'} =~ s/^\s*//; $block->{'dbk_text'} =~ s/\s*$//; return if $block->{'dbk_text'} =~ /^\s*$/; local $Text::Wrap::columns = $self->{'dbk_columns'}; $self->{'dbk_text'} .= wrap( $initial, $next, $block->{'dbk_text'} ); $self->{'dbk_text'} .= "\n"; # Flush text buffer $block->{'dbk_text'} = ""; return; } sub inline_char { my ( $self, $str ) = @_; my $block = $self->current_block(); $block->{'dbk_text'} .= $str if $block; return; } sub span_text { my ( $self, $class, $text ) = @_; $self->inline_char( "$text" ); } sub start_div { my ( $self, $class ) = @_; $self->start_block(); $self->inline_char( "
" ); return; } sub end_div { my $self = $_[0]; $self->inline_char( '
' ); $self->end_block(); return; } sub start_block { my ( $self, $left_margin_indent )= @_; $left_margin_indent ||= 0; # Flush the current block, if there is one $self->print_block(); $self->{'dbk_left_margin'} += $left_margin_indent; push @{$self->{'dbk_text_blocks'}}, { 'dbk_text' => "", 'dbk_initial_indent' => '', 'dbk_indent' => '', 'dbk_left_margin_indent' => $left_margin_indent, 'dbk_children' => 0, }; my $parent = $self->parent_block(); $parent->{'dbk_children'}++ if $parent; return $self->current_block(); } sub end_block { my ( $self ) = @_; # Flush the current block, if there is one $self->print_block(); my $block = $self->current_block(); $self->{'dbk_left_margin'} -= $block->{'dbk_left_margin_indent'}; pop @{$self->{'dbk_text_blocks'}}; return; } sub current_list { return undef unless @{$_[0]{'dbk_lists'}}; return $_[0]{'dbk_lists'}[$#{$_[0]{'dbk_lists'}}]; } sub start_list { my ( $self, $type, %attr )= @_; $self->start_block(); my $list_tag; my $item_tag; if ( $type eq 'ordered' ) { $list_tag = 'ol'; $item_tag = 'li'; } elsif ( $type eq 'itemized' ) { $list_tag = 'ul'; $item_tag = 'li'; } elsif ( $type eq 'variable' ) { $self->start_div( 'variablelist' ); $list_tag = 'dl'; $item_tag = 'dd'; } else { die "unsupported list type: '$type'\n"; } $self->inline_char( "<$list_tag>" ) unless ( $type eq 'variable' ); $self->start_block( 2 ); push @{$self->{'dbk_lists'}}, { 'dbk_type' => $type, 'dbk_list_tag' => $list_tag, 'dbk_listitem_tag' => $item_tag, %attr, }; return $self->current_list(); } sub end_list { my ( $self ) = @_; $self->end_block(); my $list = pop @{$self->{'dbk_lists'}}; my $list_tag = $list->{ 'dbk_list_tag' }; $self->inline_char( "" ); if ( $list->{'dbk_type'} eq 'variable' ) { $self->end_block(); $self->inline_char( "" ); } $self->end_block(); return; } sub dbk_para_start { my ( $self, $name, $attr )= @_; my $block = $self->start_div( 'para' ); if ( $self->in_element( "listitem" ) ) { my $parent = $self->parent_block(); my $list = $self->current_list(); # Copy listitem indent and initial_indent attribute if ( $parent->{'dbk_children'} == 1 ) { $block->{'dbk_initial_indent'} = $parent->{'dbk_initial_indent'}; } else { # Add extra space before the paragraph if it wasn't the first # and the list is compact $self->{'dbk_text'} .= "\n" if ( $parent->{'dbk_children'} > 1 && $list->{'spacing'} eq 'compact' ); # Put mark only on first para $block->{'dbk_initial_indent'} = $parent->{'dbk_indent'}; } $block->{'dbk_indent'} = $parent->{'dbk_indent'}; } return; } sub dbk_para_end { $_[0]->end_div(); return; } sub dbk_itemizedlist_start { my ( $self, $name, $attr )= @_; $self->start_list( 'itemized', 'mark' => '-', 'spacing' => 'normal', %$attr ); return; } sub dbk_itemizedlist_end { $_[0]->end_list(); return; } sub dbk_orderedlist_start { my ( $self, $name, $attr )= @_; $self->start_list( 'ordered', 'spacing' => 'normal', %$attr, 'item_count' => 0 ); return; } sub dbk_orderedlist_end { $_[0]->end_list(); return; } sub dbk_variablelist_start { my ( $self, $name, $attr )= @_; $self->start_list( 'variable', 'spacing' => 'normal', %$attr ); return; } sub dbk_variablelist_end { $_[0]->end_list(); return; } sub dbk_varlistentry_start { my $self = $_[0]; my $list = $self->current_list(); return unless defined( $list ); if ( !$list->{'_list_started'} ) { $self->inline_char( "<$list->{'dbk_list_tag'}>" ); $self->start_block( 2 ); $list->{'_list_started'} = 'yes'; } return; } sub dbk_listitem_start { my ( $self, $name, $attr )= @_; $self->start_block(); my $list = $self->current_list(); return unless defined( $list ); $self->inline_char( "<$list->{'dbk_listitem_tag'}>" ); $self->start_block( 2 ); return; } sub dbk_listitem_end { my $self = $_[0]; $self->end_block(); my $list = $self->current_list(); return unless defined( $list ); $self->inline_char( "{'dbk_listitem_tag'}>" ); $self->end_block(); return; } sub admonition_start { my ( $self, $name, $attr ) = @_; $self->start_div( $name ); $self->span_text( 'admonition', ucfirst( $name . ":" ) ); $self->start_block( 2 ); return; } sub admonition_end { my $self = $_[0]; $self->end_block(); $self->end_div(); return; } sub mapped_start { my ( $self, $name ) = @_; $self->inline_char( "<$dbk2html{$name}>" ); return; } sub mapped_end { my ( $self, $name ) = @_; $self->inline_char( "" ); return; } sub span_start { my ( $self, $name, $attr ) = @_; $self->inline_char( "" ); return; } sub span_end { my ( $self, $name ) = @_; $self->inline_char( "" ); return; } sub var_start { my ( $self, $name, $attr ) = @_; $self->inline_char( "" ); return; } sub var_end { my ( $self, $name, $attr ) = @_; $self->inline_char( "" ); return; } sub dbk_email_end { my ( $self, $name ) = @_; my $email = $self->get_collector( $name ); $_[0]->inline_char( "$email" ); return; } sub dbk_term_start { my ( $self, $name, $attr )= @_; my $block = $self->start_block(); $self->collector_start( $name ); return; } sub dbk_term_end { my ( $self, $name ) = @_; $self->inline_char( "
" . $self->get_collector( $name ). "
" ); $self->end_block(); return; } sub dbk_title_start { my ( $self, $name, $attr )= @_; $self->start_block( 0 ); $self->span_start( $name ); return; } sub dbk_title_end { my ( $self, $name ) = @_; $self->span_end( $name ); $_[0]->end_block(); return; } sub dbk_ulink_start { my ( $self, $name, $attr )= @_; my $url = $attr->{'url'} || ''; $self->{'dbk_curr_url_attr'} = $url; $self->inline_char( "" ); return; } sub dbk_ulink_end { my ( $self ) = @_; $self->inline_char( '' ); delete $self->{'dbk_curr_url_attr'}; delete $self->{'dbk_curr_url'}; return; } sub dbk_ulink_char { my ( $self, $str )= @_; my $cdata = ( $str ne '' ? $str : $self->$self->{'dbk_curr_url_attr'} ); $self->inline_char( $cdata ); return; } =pod =head1 dbk2html( $docbook_str, [$columns], [$xhtml] ) Returns an HTML version of the DocBook XML fragment $docbook_str. The C parameter sets the number of columns in which the DocBook HTML text should be formatted. The C parameter defines whether the generated code will be XHTML-compliant; the default is yes. This method will die() in case of error. =cut sub dbk2html { my ( $docbook_str, $columns, $xhtml ) = @_; $xhtml = 1 unless defined $xhtml; $docbook_str = ensure_utf8( $docbook_str ); my %args = ( 'dbk_columns' => $columns, 'xhtml' => $xhtml ); my $parser = new Lire::ReportParser::HTMLDocBookFormatter( %args ); my $str = < $docbook_str EOD return $parser->parse( $str ); } 1; __END__ =head1 SEE ALSO Lire::ReportParser(3pm) Lire::ReportParser::AsciiDocBookFormatter(3pm) =head1 VERSION $Id: HTMLDocBookFormatter.pm,v 1.10 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/ReportParser/HTMLWriter.pm0000644000175000017500000004762510460673257016557 00000000000000package Lire::ReportParser::HTMLWriter; use strict; use Carp; use File::Basename; use File::Copy; use Locale::TextDomain 'lire'; use POSIX qw/ strftime /; use Lire::Config::Build qw/ ac_path /; use Lire::DlfSchema; use Lire::Error qw/ file_not_readable /; use Lire::DataTypes qw/ check_bool eval_bool /; use Lire::ReportParser::ReportBuilder; use Lire::ReportParser::HTMLDocBookFormatter qw/ dbk2html /; use Lire::Utils qw/ check_param check_object_param create_file indent is_url text_for_width xml_encode /; use Lire::I18N qw/set_fh_encoding /; =pod =head1 NAME Lire::ReportParser::HTMLWriter - converting lire XML reports to HTML =head1 SYNOPSIS use Lire::ReportParser::HTMLWriter; my $writer = new Lire::ReportParser::HTMLWriter(); $writer->write_report( $report, $outputdir, 'xhtml' => 0, 'one_page' => 0 ); =head1 DESCRIPTION An object capable of formatting a Lire::Report to HTML in the directory named $outputdir. =cut sub new { return bless {}, shift; } sub write_report { my ( $self, $report, $outputdir, %args ) = @_; check_object_param( $report, 'report', 'Lire::Report' ); check_param( $outputdir, 'outputdir' ); check_param( $args{'xhtml'}, 'xhtml', \&check_bool, "'xhtml' parameter should be a BOOLEAN (1 or 0)" ) if defined( $args{'xhtml'} ); check_param( $args{'one_page'}, 'one_page', \&check_bool, "'one_page' parameter should be a BOOLEAN (1 or 0)" ) if defined( $args{'one_page'} ); mkdir $outputdir or die "mkdir $outputdir failed: $!\n" unless -d $outputdir; die "can't write to $outputdir" unless -w $outputdir; $self->{'_report'} = $report; $self->{'_outputdir'} = $outputdir; $self->{'_one_page'} = ( defined $args{'one_page'} ? eval_bool( $args{'one_page'} ) : 0 ); $self->{'_xhtml'} = ( defined $args{'xhtml'} ? eval_bool( $args{'xhtml'} ) : 1 ); $self->{'_etag'} = $self->{'_xhtml'} ? ' />' : '>'; $self->start_page( 'index.html' ) if $self->{'_one_page'}; $self->write_toc(); my $i = 1; my $nsections = $report->sections(); foreach my $section ( $report->sections() ) { $self->{'_next'} = ( $i == $nsections ? $report->schemas()->[0] . ".html" : "section-" . ($i + 1) . ".html" ); $self->write_section( $section, $i ); $i++; } $i = 0; my $schemas = $report->schemas(); foreach my $schema ( @$schemas ) { $self->{'_next'} = ( $i == $#{$schemas} ? undef : $schemas->[$i+1] . ".html" ); $self->write_schema( $schema ); $i++; } $self->end_page() if $self->{'_one_page'}; $self->copy_html_files(); return; } sub write_links { my $self = $_[0]; my $css = Lire::Config->get( 'lr_html_css' ); my $link_infos = [ [ 'stylesheet', is_url( $css ) ? $css : basename( $css ), 'text/css', 1 ], [ 'author', 'http://www.logreport.org/', 'The LogReport Foundation', 1 ], [ 'help', 'http://logreport.org/doc/lire/', 'Lire documentation', 1 ], [ 'start', 'index.html', __( 'Table Of Contents' ), ! $self->{'_one_page'} ], [ 'first', 'section-1.html', __( 'First Section' ), ! $self->{'_one_page'} ], [ 'last', "section-" . $self->{'_report'}->sections() . ".html", __( 'Last Section' ), ! $self->{'_one_page'} ], [ 'prev', $self->{'_prev'}, __( 'Previous Page' ), ! $self->{'_one_page'} && $self->{'_prev'} ], [ 'next', $self->{'_next'}, __( 'Next Page' ), ! $self->{'_one_page'} && $self->{'_next'}], ]; my $fh = $self->{'_fh'}; foreach my $link ( @$link_infos ) { my ( $rel, $href, $title, $cond ) = @$link; next unless $cond; print $fh ' {'_etag'}, "\n"; } return; } sub report_title { my ( $self, $title ) = @_; my $report_title = $self->{'_report'}->title() || __( 'Lire Report' ); return xml_encode( $title ? $report_title .' : '. $title : $report_title ); } sub write_chart { my ( $self, $subreport, $chart_config ) = @_; my $fh = $self->{'_fh'}; my $type = $chart_config->type(); my $title = $chart_config->title(); $title = xml_encode( $title ) if $title; my $file = eval { $type->write_chart( $chart_config, $subreport, 'outputdir' => $self->{'_outputdir'}, 'format' => 'png' ) }; if ( $@ ) { print $fh ' ' x 8, '
', "\n", ' ' x 10, __x( 'An error occured while generating the chart: {error}', 'error' => $@ ), ' ' x 8, "
\n"; } elsif ( $file ) { my $base = basename( $file ); print $fh < $title{'_etag'} CHART } return; } sub write_table_header { my ( $self, $subreport ) = @_; my $fh = $self->{'_fh'}; my $info = $subreport->table_info(); print $fh ' ' x 8, "\n", ' ' x 10, "\n"; foreach my $row ( @{ $info->header_rows() } ) { my $skip = 0; print $fh ' ' x 12, '', "\n"; foreach my $cell ( @$row ) { if ( $skip > 0 ) { $skip--; next; } print $fh ' ' x 14; unless ( defined $cell ) { print $fh '', "\n"; next; } if ( $cell->col_start() != $cell->col_end() ) { $skip = $cell->col_end() - $cell->col_start(); print $fh '\n"; } print $fh ' ' x 12, "\n"; } print $fh ' ' x 10, "\n"; return; } sub write_table_footer { my ( $self, $subreport ) = @_; my $fh = $self->{'_fh'}; print $fh ' ' x 10, "\n", ' ' x 12, "\n"; my @values = grep { $_->class() eq 'numerical' } $subreport->table_info()->column_infos(); print $fh ' ' x 14, '\n"; my $next = $values[0]->col_start(); foreach my $col_info ( @values ) { my $curr = $col_info->col_start(); while ( $next < $curr ) { print $fh ' ' x 14, '', "\n"; $next++; } my $value = $subreport->get_summary_value( $col_info->name() ); print $fh ' ' x 14, '\n"; $next = $col_info->col_start() + 1; } print $fh ' ' x 12, "\n", ' ' x 10, "\n"; return; } sub html_value { my ( $self, $string, $max_width ) = @_; $max_width = 180 unless defined $max_width; $max_width = 5 if ( $max_width < 5 ); my $link; my $cropped_string = xml_encode( text_for_width( $string, $max_width ) ); if ( $string =~ m@^[a-zA-Z]+://@ ) { $link = "$cropped_string"; } elsif ( $string =~ m/([\.a-zA-Z0-9_+\#\$-]+@[\.a-zA-Z0-9_+\#\$-]+)/ ) { $link = "$cropped_string"; } else { $link = $cropped_string; } return $link; } sub write_schema { my ($self, $schema_id) = @_; my $schema = Lire::DlfSchema::load_schema( $schema_id ); unless ( $self->{'_one_page'} ) { $self->start_page( "$schema_id.html", $schema->title() ); } my $fh = $self->{'_fh'}; print $fh '
', "\n"; print $fh '

', xml_encode( $schema->title() ), "

\n" if $self->{'_one_page'}; print $fh "
\n"; foreach my $field ( $schema->fields() ) { next if $field->name() =~ /^(dlf_id|dlf_source)$/; my $name = $self->{'_one_page'} ? "schema:$schema_id:" . $field->name() : $field->name(); my $label = xml_encode( $field->label() ); my $desc = $field->description ? dbk2html( $field->description() ) : __( 'No description.' ); print $fh <$label
$desc
TERM } print $fh <
SECTION unless ( $self->{'_one_page'} ) { $self->end_page(); $self->{'_prev'} = "$schema_id.html"; } return; } sub write_table_entries { my ( $self, $subreport ) = @_; my $fh = $self->{'_fh'}; unless ( $subreport->entries() ) { print $fh ' ' x 10, "\n", ' ' x 12, "\n", ' ' x 14, '\n", ' ' x 12, "\n", ' ' x 10, "\n", ' ' x 8, "
'; } else { print $fh ''; } my $schema = $subreport->field_schema( $cell->name() ); print $fh 'name(), '">' if $schema; print $fh xml_encode( $cell->label() ); print $fh '' if $schema; print $fh "
', __x( 'Total for {nrecords} records', 'nrecords' => $subreport->nrecords() ), "', $self->html_value( $value->{'content'}, 50 ), "
', __( 'There is no entries in this table.' ), "
\n"; return; } print $fh ' ' x 10, "\n"; foreach my $row ( @{$subreport->getrows()} ) { my $skip = 0; print $fh ' ' x 12, "\n"; foreach my $cell ( @$row ) { if ( $skip > 0 ) { $skip--; next; } print $fh ' ' x 14; unless ( defined $cell ) { print $fh '', "\n"; next; } my $col_info = $cell->{'col_info'}; if ( $col_info->col_start() != $col_info->col_end() ) { $skip = $col_info->col_end() - $col_info->col_start(); print $fh '', $self->html_value( $cell->{'content'} ), "\n"; } print $fh ' ' x 12, "\n"; } print $fh ' ' x 10, "\n", ' ' x 8, "\n"; return; } sub write_subreport { my ( $self, $subreport ) = @_; my $fh = $self->{'_fh'}; my $id = $subreport->id(); my $title = xml_encode( $subreport->title() ); my $desc = $subreport->description() ? dbk2html( $subreport->description() ) : ''; print $fh <

$title

$desc
SUBREPORT if ( $subreport->is_missing() ) { print $fh ' ' x 8, '
', "\n", ' ' x 10, __x( 'This report is missing: {reason}', 'reason' => xml_encode( $subreport->missing_reason() ) ), "\n", ' ' x 8, '
', "\n", ' ' x 6, "\n"; return; } foreach my $cfg ( @{$subreport->chart_configs()} ) { $self->write_chart( $subreport, $cfg ); } $self->write_table_header( $subreport ); $self->write_table_footer( $subreport ); $self->write_table_entries( $subreport ); print $fh ' ' x 6, "\n"; return; } sub write_section { my ( $self, $section, $index ) = @_; unless ( $self->{'_one_page'} ) { $self->start_page( "section-$index.html", $section->title() ); } my $fh = $self->{'_fh'}; print $fh '
', "\n", '

'; print $fh '' if $self->{'_one_page'}; print $fh xml_encode( $section->title() ); print $fh '' if $self->{'_one_page'}; print $fh "

\n"; print $fh '
', "\n", ' ', dbk2html( $section->description() ), "\n", '
', "\n" if $section->description(); if ( $section->subreports() ) { foreach my $subreport ( $section->subreports() ) { $self->write_subreport( $subreport ); } } else { print $fh '

', __( 'No subreports were generated for this section.' ), "

\n"; } print $fh "
\n"; unless ( $self->{'_one_page'} ) { $self->end_page(); $self->{'_prev'} = "section-$index.html"; } return; } sub write_toc { my $self = $_[0]; unless ( $self->{'_one_page'} ) { $self->{'_next'} = 'section-1.html'; $self->start_page( 'index.html', __( 'Table Of Contents' ) ); } my $fh = $self->{'_fh'}; print $fh '
', "\n"; print $fh '

', __( 'Table Of Contents' ), "

\n" if $self->{'_one_page'}; print $fh '
    ', "\n"; my $i = 1; foreach my $section ( $self->{'_report'}->sections() ) { $self->write_section_toc( $section, $i ); $i += 1; } foreach my $schema_id ( @{$self->{'_report'}->schemas()} ) { my $schema = Lire::DlfSchema::load_schema( $schema_id ); my $href = $self->{'_one_page'} ? "#schema:" . $schema_id : $schema_id . ".html"; $self->write_toc_link( $href, $schema->title(), 8 ); } print $fh <
TOC unless ( $self->{'_one_page'} ) { $self->end_page(); $self->{'_toc'} = 'index.html'; $self->{'_prev'} = 'index.html'; } return; } sub write_section_toc { my ( $self, $section, $idx ) = @_; my $href = $self->{'_one_page'} ? "#section-$idx" : "section-$idx.html"; my $title = xml_encode( $section->title() ); my $fh = $self->{'_fh'}; print $fh <
$title
    SECTION foreach my $subreport ( $section->subreports() ) { my $href = $self->{'_one_page'} ? '#' . $subreport->id() : "section-$idx.html#" . $subreport->id(); $self->write_toc_link( $href, $subreport->title(), 14 ); } print $fh <
SECTION return; } sub write_toc_link { my ( $self, $href, $title, $indent ) = @_; print {$self->{'_fh'}} ' ' x $indent, '
  • ', xml_encode( $title ), '
  • ', "\n"; return; } sub write_navbar { my $self = $_[0]; return if $self->{'_one_page'}; my $fh = $self->{'_fh'}; print $fh ' \n"; return; } sub write_report_infos { my $self = $_[0]; my $fh = $self->{'_fh'}; my $format = '%Y-%m-%d %H:%M:%S %Z'; print $fh '
    ', "\n"; print $fh ' ', __x( 'Report generated on: {date}', 'date' => strftime( $format, localtime( $self->{'_report'}->date() ) ) ); print $fh "{'_etag'}\n"; my $period; if ( $self->{'_report'}->timespan_start() ) { $period = strftime( $format, localtime( $self->{'_report'}->timespan_start() ) ) . ' - ' . strftime( $format, localtime( $self->{'_report'}->timespan_end() ) ); } else { $period = __( 'Unknown Period' ); } print $fh ' ', __x( 'Reporting on period: {period}', 'period' => $period ), "{'_etag'}\n
    \n"; return; } sub write_logo { my $self = $_[0]; my $logo = Lire::Config->get( 'lr_logo' ); return unless $logo; my $url = Lire::Config->get( 'lr_logo_url' ); my $fh = $self->{'_fh'}; print $fh ' ', "\n"; return; } sub start_page { my ( $self, $page, $title ) = @_; open $self->{'_fh'}, "> $self->{'_outputdir'}/$page" or die "can't write to '$self->{'_outputdir'}/$page': $!\n"; set_fh_encoding( $self->{'_fh'}, 'utf-8' ); my $fh = $self->{'_fh'}; if ( $self->{'_xhtml'} ) { print $fh < DTD } else { print $fh < DTD } my $page_title = $self->report_title( $title ); print $fh < $page_title {'_etag'} HEAD $self->write_links(); print $fh <
    BODY $self->write_logo(); $self->write_navbar(); $title = $title ? xml_encode( $title ) : $self->report_title(); print $fh <$title TITLE $self->write_report_infos(); print $fh "
    \n"; return; } sub end_page { my $self = $_[0]; print {$self->{'_fh'}} < HTML $self->{'_fh'}->close(); $self->{'_fh'} = undef; return; } sub copy_html_files { my $self = $_[0]; my $logo = Lire::Config->get( 'lr_logo' ); copy( $logo, $self->{'_outputdir'} ) unless is_url( $logo ); my $css = Lire::Config->get( 'lr_html_css' ); copy( "$css", $self->{'_outputdir'} ) unless is_url( $css ); unless ( $self->{'_one_page'} ) { my $html_dir = ac_path( 'datadir', 'PACKAGE' ) . '/html'; foreach my $file ( qw/ toc.png prev.png next.png / ) { copy( "$html_dir/$file", $self->{'_outputdir'} ); } } return; } # keep perl happy 1; __END__ =pod =head1 AUTHORS Wolfgang Sourdeau Francis J. Lacoste =head1 VERSION $Id: HTMLWriter.pm,v 1.35 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/ReportParser/LaTeXWriter.pm0000644000175000017500000003467010462720616016756 00000000000000package Lire::ReportParser::LaTeXWriter; use strict; use Lire::Utils qw/check_param check_object_param latex_encode file_content/; use Lire::I18N qw/ set_fh_encoding/; use Lire::ReportParser::LaTeXDocBookFormatter qw/dbk2latex/; use Lire::DlfSchema; use File::Basename qw/dirname basename/; use POSIX qw/strftime/; use Locale::TextDomain 'lire'; use Lire::Config; =pod =head1 NAME Lire::ReportParser::LaTeXWriter - Lire::ReportParser processor that formats the report in LaTeX =head1 SYNOPSIS use Lire::ReportParser::LaTeXWriter; use Lire::ReportParser::ReportBuilder; my $writer = new Lire::ReportParser::LaTeXWriter(), ); my $parser = new Lire::ReportParser::ReportBuilder(); my $report = $parser->parsefile( 'report.xml' ); $parser->write_report( $report, 'report.pdf', 'pdf', 'preamble' => 'myfont.tex' ); =head1 DESCRIPTION This is a Lire::ReportParser processor which will format the XML report into PDF, PS or DVI format using LaTeX as intermediary format. =head1 METHODS =head2 new() Returns an new LaTeXWriter. =cut sub new { return bless {}, shift; } =pod =head2 write_report( $report, $outputfile, $format, [ $preamble ] ) This will write the report Lire::Report in $outputfile in $format output format. =over =item outputfile This manadatory parameter specifies the file where the file will be written. =item format This mandatory parameter may be one of 'pdf', 'ps', 'dvi' or 'latex'. =item preamble This optional parameter can be used to specify a file that will be included in the LaTeX preamble. It can be use to change the fonts for example. =cut sub write_report { my ( $self, $report, $outputfile, $format, $preamble ) = @_; check_object_param( $report, 'report', 'Lire::Report' ); check_param( $outputfile, 'outputfile' ); # \s is for broken cperl-mode in Emacs, *sigh* check_param( $format, 'format', qr/^(dvi|ps|pdf|latex)$/, 'format should be one of dvi, ps, pdf or latex' ); check_param( $preamble, 'preamble', sub { -r $preamble }, "preamble file isn't readable" ) if $preamble; $self->{'_chart_files'} = []; $self->{ '_format'} = $format; $self->{'_outputfile'} = $outputfile; $self->{'_outputdir'} = dirname( $outputfile ); $self->{'_outputbase'} = basename( $outputfile ); $self->{'_outputbase'} =~ s/\.\w+?$//; $self->{'_preamble'} = $preamble; open $self->{'_fh'}, "> $self->{'_outputdir'}/$self->{'_outputbase'}.tex" or die "can't write to $self->{'_outputdir'}/$self->{'_outputbase'}.tex\n"; set_fh_encoding( $self->{'_fh'}, 'utf-8' ); $self->write_header(); $self->write_titlepage( $report ); foreach my $section ( $report->sections() ) { $self->write_section( $section ); } $self->write_appendix( $report ); print {$self->{'_fh'}} "\\end{document}\n"; $self->process_latex(); return; } sub write_header { my $self = $_[0]; my $hyperref = $self->{'_format'} eq 'pdf' ? 'ps2pdf' : 'dvips'; my $graphics = $self->{'_format'} eq 'pdf' ? 'dvipdf' : 'dvips'; my $unicode = Lire::Config->get( 'unicode.tex' ); my $fh = $self->{'_fh'}; print $fh <<'EOF'; \ocp\MyTexUTF=inutf8 \InputTranslation currentfile \MyTexUTF \documentclass{report} \addtolength{\textwidth}{2\oddsidemargin} \addtolength{\textheight}{2\topmargin} \setlength{\oddsidemargin}{0cm} \setlength{\topmargin}{0cm} EOF print $fh '\input ', $unicode, "\n", <{'_preamble'}, "\n" if $self->{'_preamble'}; print $fh "\n", '\begin{document}', "\n"; return; } sub write_titlepage { my ( $self, $report ) = @_; my $fh = $self->{'_fh'}; if ( $report->title() ) { print $fh '\title{', latex_encode( $report->title() ) ,"}\n" } else { print $fh '\title{}', "\n"; } print $fh '\author{}', "\n"; my $fmt = '%Y-%m-%d %H:%M'; my $start = strftime( $fmt, localtime( $report->timespan_start() ) ); my $end = strftime( $fmt, localtime( $report->timespan_end() ) ); my $date = strftime( $fmt, localtime( $report->date() ) ); print $fh '\date{', __x( "Report for {start} -- {end}", 'start' => $start, 'end' => $end ), "\\\\\n", __x( 'Report generated {date}', 'date' => $date ), "}\n", '\maketitle', "\n", '\tableofcontents', "\n\n"; return; } sub write_section { my ( $self, $section ) = @_; my $fh = $self->{'_fh'}; print $fh '\chapter{', latex_encode( $section->title() ), "}\n\n"; print $fh dbk2latex( $section->description() ) if $section->description(); foreach my $subreport ( $section->subreports() ) { if ( $subreport->is_missing() ) { $self->write_missing_subreport( $subreport ); } else { $self->write_subreport( $subreport ); } } return; } sub write_subreport { my ( $self, $subreport ) = @_; my $fh = $self->{'_fh'}; print $fh '\section{', latex_encode( $subreport->title() ), "}\n\n"; print $fh dbk2latex( $subreport->description() ) if $subreport->description(); foreach my $cfg ( @{$subreport->chart_configs()} ) { $self->write_chart( $subreport, $cfg ); } $self->write_table_header( $subreport ); $self->write_table_footer( $subreport ); $self->write_table_entries( $subreport ); return; } sub write_missing_subreport { my ( $self, $subreport ) = @_; my $fh = $self->{'_fh'}; print $fh '\section{', latex_encode( $subreport->title() ), "}\n\n"; print $fh '\emph{', __x( 'This report is missing: {reason}', 'reason' => latex_encode( $subreport->missing_reason() ) ), "}\n\n"; return; } sub write_chart { my ( $self, $subreport, $chart_config ) = @_; my $fh = $self->{'_fh'}; my $type = $chart_config->type(); my $font = Lire::Config->get( 'lr_chart_font' ); $font ||= '/Helvetica'; if ( substr( $font, 0, 1) ne '/' ) { warn "'lr_chart_font' contains an invalid PostScript font ('$font'), using '/Helvetica'"; $font = '/Helvetica'; } my $file = eval { $type->write_chart( $chart_config, $subreport, 'outputdir' => $self->{'_outputdir'}, 'format' => 'eps', 'font' => $font ) }; if ( $@ ) { print $fh '\emph{', latex_encode( __x( 'An error occured while generating the chart: {error}', 'error' => $@ ) ), "}\n\n"; } elsif ( $file ) { my $base = basename( $file ); push @{$self->{'_chart_files'}}, $file; print $fh "\\begin{center}\n\\includegraphics{$base}\n\\end{center}\n\n"; } return; } sub write_table_header { my ( $self, $subreport ) = @_; my $fh = $self->{'_fh'}; my $info = $subreport->table_info(); my $col_spec = join( '', '|', ( map { $_->class() eq 'categorical' ? 'l' : 'r' } $info->column_infos() ), '|' ); print $fh "\\begin{longtable}{$col_spec}\n\\hline\n"; my @col_infos = $info->column_infos(); foreach my $row ( @{ $info->header_rows() } ) { my @data = (); foreach my $cell ( @$row ) { next unless defined $cell; my $i = $cell->col_start(); my $schema = $subreport->field_schema( $cell->name() ); if ( $schema ) { $data[$i] = '\bfseries \hyperlink{' . $schema . ':' . $cell->name() . '}{' . latex_encode( $cell->label() ) . '}'; } else { $data[$i] = '\bfseries ' . latex_encode( $cell->label() ); } } $self->write_table_row( \@col_infos, \@data ); } print $fh "\\hline\n\\endhead\n\n"; return; } sub write_table_entries { my ( $self, $subreport ) = @_; my $fh = $self->{'_fh'}; unless ( $subreport->entries() ) { print $fh '\multicolumn{', $subreport->table_info()->ncols(), '}{|l|}{\emph{', __( 'There is no entries in this table.' ), "}}\\\\\n\\end{longtable}\n\n"; return; } my @col_infos = $subreport->table_info()->column_infos(); foreach my $row ( @{$subreport->getrows()} ) { my @data = map { defined $_ ? latex_encode( $_->{'content'} ) : undef } @$row; $self->write_table_row( \@col_infos, \@data ); } print $fh "\\end{longtable}\n\n"; return; } sub write_table_row { my ( $self, $infos, $row, $link ) = @_; my $fh = $self->{'_fh'}; my $skip = 0; for ( my $i=0; $i < @$infos; $i++ ) { if ( $skip ) { $skip--; next; } my $col_info = $infos->[$i]; if ( defined $row->[$i] && $col_info->col_start() != $col_info->col_end() ) { my $spec = ''; $spec .= '|' if $col_info->col_start() eq 0; $spec .= $col_info->class() eq 'categorical' ? 'l' : 'r'; $spec .= '|' if $col_info->col_start() eq $#$infos; print $fh '\multicolumn{', ($col_info->col_end() - $col_info->col_start()) + 1, '}{', $spec, '}{', $row->[$i], '}'; $skip = $col_info->col_end() - $col_info->col_start(); } elsif ( defined $row->[$i] ) { print $fh $row->[$i]; } print $fh " & " if $i != $#$infos; } print $fh "\\\\\n"; return; } sub write_table_footer { my ( $self, $subreport ) = @_; my $fh = $self->{'_fh'}; print $fh "\\hline\n\\multicolumn{", $subreport->table_info()->ncols(), '}{r}{\emph{', __( 'continued on next page' ), "}}\n\\endfoot\n\\hline\n"; my @values = grep { $_->class() eq 'numerical' } $subreport->table_info()->column_infos(); print $fh '\multicolumn{', $values[0]->col_start(), '}{|l}{\emph{', __x( 'Total for {nrecords} records', 'nrecords' => $subreport->nrecords() ), '}} & '; my @row = (); foreach my $col_info ( @values ) { $row[ $col_info->col_start() ] = latex_encode( $subreport->get_summary_value( $col_info->name() )->{'content'} ); } print $fh join ( ' & ', map { defined $_ ? $_ : '' } @row[ $values[0]->col_start() .. $#row ] ); print $fh "\\\\\n\\hline\n\\endlastfoot\n\n"; return; } sub write_appendix { my ( $self, $report ) = @_; my $fh = $self->{'_fh'}; print $fh "\\appendix\n"; foreach my $schema ( @{ $report->schemas() } ) { $self->write_schema( $schema ); } return; } sub write_schema { my ( $self, $schema_id ) = @_; my $schema = Lire::DlfSchema::load_schema( $schema_id ); my $fh = $self->{'_fh'}; print $fh '\chapter{', latex_encode( $schema->title() ), "}\n\n"; print $fh dbk2latex( $schema->description() ) if $schema->description(); print $fh '\begin{description}', "\n"; foreach my $field ( $schema->fields() ) { next if $field->name() =~ /(dlf_id|dlf_source)/; # Skip internal print $fh '\item[\hypertarget{', $schema_id, ":", $field->name(), '}{', latex_encode( $field->label() ), "}]\n"; print $fh dbk2latex( $field->description() ) if $field->description(); } print $fh '\end{description}', "\n\n"; return; } sub process_latex { my $self = $_[0]; return if $self->{'_format'} eq 'latex'; $self->create_dvi(); $self->create_ps() if $self->{'_format'} =~ /ps|pdf/; $self->create_pdf() if $self->{'_format'} eq 'pdf'; my @clean = ( "$self->{'_outputbase'}.tex", "$self->{'_outputbase'}.log", "$self->{'_outputbase'}.aux", "$self->{'_outputbase'}.toc", "$self->{'_outputbase'}.out", "$self->{'_outputbase'}.ofl"); push @clean, "$self->{'_outputbase'}.dvi", @{$self->{'_chart_files'}} if $self->{'_format'} =~ /^(ps|pdf)$/; push @clean, "$self->{'_outputbase'}.ps" if $self->{'_format'} eq 'pdf'; unlink( @clean ); return; } sub create_dvi { my $self = $_[0]; my $lambda = Lire::Config->get( 'lambda_path' ); my $status = system( "cd $self->{'_outputdir'} && $lambda -interaction=batchmode $self->{'_outputbase'} >/dev/null 2>/dev/null" ); my $log = file_content( "$self->{'_outputdir'}/$self->{'_outputbase'}.log" ); if ( !$status ) { # No error, check for rerun $self->create_dvi() if $log =~ /rerun/i; } else { die "Error processing LaTeX file $self->{'_outputbase'}.tex:\n" . join ( "", $log =~ /^(!.*)$/mg ); } return; } sub create_ps { my $self = $_[0]; my $odvips = Lire::Config->get( 'odvips_path' ); my $printer = $self->{'_format'} eq 'pdf' ? 'pdf' : 'ps'; my $status = system( "cd $self->{'_outputdir'} && $odvips -o $self->{'_outputbase'}.ps -P$printer -q $self->{'_outputbase'} > $self->{'_outputbase'}.log 2>&1 " ); die ("Error converting file $self->{'_outputbase'}.dvi to PS:\n", file_content( "$self->{'_outputbase'}.log" ) ) if $status; return; } sub create_pdf { my $self = $_[0]; my $ps2pdf = Lire::Config->get( 'ps2pdf_path' ); my $status = system( "cd $self->{'_outputdir'} && $ps2pdf -dAutoRotatePages=/None $self->{'_outputbase'}.ps >$self->{'_outputbase'}.log 2>&1" ); die ("Error converting file $self->{'_outputbase'}.ps to PDF:\n", file_content( "$self->{'_outputbase'}.log" ) ) if $status; return; } 1; __END__ =pod =head1 SEE ALSO Lire::ReportParser::LaTeXDocBookFormatter(3pm) Lire::OutputFormat(3pm) Lire::OutputFormats::LaTeX(3pm) =head1 VERSION $Id: LaTeXWriter.pm,v 1.17 2006/07/29 17:57:34 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/ReportParser/Makefile.am0000644000175000017500000000337610105265733016277 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.16 2004/08/07 23:55:07 flacoste Exp $ ## Copyright (C) 2000-2001 Stichting LogReport Foundation LogReport@LogReport.org ## ## This file is part of Lire. ## ## Lire is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk allperllibdir = $(LR_PERL5LIBDIR)/Lire/ReportParser allperllib_DATA = \ AsciiDocBookFormatter.pm \ AsciiWriter.pm \ ExcelWriter.pm \ HTMLDocBookFormatter.pm \ HTMLWriter.pm \ LaTeXDocBookFormatter.pm \ LaTeXWriter.pm \ ReportBuilder.pm \ RowColHandler.pm man_MANS = \ AsciiDocBookFormatter.3pm \ AsciiWriter.3pm \ ExcelWriter.3pm \ HTMLDocBookFormatter.3pm \ LaTeXDocBookFormatter.3pm \ LaTeXWriter.3pm \ ReportBuilder.3pm \ HTMLWriter.3pm \ RowColHandler.3pm perlpackage = Lire::ReportParser transform = s,^,$(perlpackage)::, EXTRA_DIST = $(allperllib_DATA) CLEANFILES = $(man_MANS) lire-2.1.1/all/lib/Lire/ReportParser/Makefile.in0000644000175000017500000004373511677606132016322 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/include/rules.mk subdir = all/lib/Lire/ReportParser ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(allperllib_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) transform = s,^,$(perlpackage)::, ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done allperllibdir = $(LR_PERL5LIBDIR)/Lire/ReportParser allperllib_DATA = \ AsciiDocBookFormatter.pm \ AsciiWriter.pm \ ExcelWriter.pm \ HTMLDocBookFormatter.pm \ HTMLWriter.pm \ LaTeXDocBookFormatter.pm \ LaTeXWriter.pm \ ReportBuilder.pm \ RowColHandler.pm man_MANS = \ AsciiDocBookFormatter.3pm \ AsciiWriter.3pm \ ExcelWriter.3pm \ HTMLDocBookFormatter.3pm \ LaTeXDocBookFormatter.3pm \ LaTeXWriter.3pm \ ReportBuilder.3pm \ HTMLWriter.3pm \ RowColHandler.3pm perlpackage = Lire::ReportParser EXTRA_DIST = $(allperllib_DATA) CLEANFILES = $(man_MANS) all: all-am .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/Lire/ReportParser/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/Lire/ReportParser/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man3: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list=''; test -n "$(man3dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } install-allperllibDATA: $(allperllib_DATA) @$(NORMAL_INSTALL) test -z "$(allperllibdir)" || $(MKDIR_P) "$(DESTDIR)$(allperllibdir)" @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(allperllibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(allperllibdir)" || exit $$?; \ done uninstall-allperllibDATA: @$(NORMAL_UNINSTALL) @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(allperllibdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(allperllibdir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-allperllibDATA install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man3 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-allperllibDATA uninstall-man uninstall-man: uninstall-man3 .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ distclean distclean-generic distdir dvi dvi-am html html-am \ info info-am install install-allperllibDATA install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-man3 \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall \ uninstall-allperllibDATA uninstall-am uninstall-man \ uninstall-man3 .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lire-2.1.1/all/lib/Lire/ReportParser/RowColHandler.pm0000644000175000017500000002121210460673257017301 00000000000000package Lire::ReportParser::RowColHandler; use strict; use base qw/ Lire::ReportParser /; =pod =head1 NAME Lire::ReportParser::RowColHandler - Lire::ReportParser subclass which synthetize row =head1 SYNOPSIS In XML Report processors: package MyParser; use base qw/Lire::ReportParser::RowColHandler/; sub handle_header_row { my ( $self, $row ) = @_; ... } sub handle_row { my ( $self, $row ) = @_; ... } sub handle_table_summary { my ( $self, $nrecords, $row ) = @_; .... } =head1 DESCRIPTION The Lire::ReportParser::RowColHandler module is a Lire::ReportParser subclass which will synthetize handle_row() events. This makes it easier to write subclases which onlypurpose is to format the report. Instead of having to reconstruct the table row from the various entry_start, group_start, handle_name, events, the subclass only has to process handle_row() events. =head1 USING Lire::ReportParser::RowColHandler Client only have to inherit from Lire::ReportParser::RowColHandler. After that, they can define handle_row(), handle_header_row() and handle_table_summary() method. There is a parameter that the RowColHandler accepts and its C which specify when the handle_table_summary() event will be synthetised ( C or C the table's body.) When it's C the event will be generated after the header_row events but before any handle_row() events. Otherwise, it will be generated once all handle_row() events are processed. The default is C. =cut sub new { my ( $class, %params ) = @_; my $self = $class->SUPER::new( %params ); $self->{'lrc_summary_when'} = $params{'summary_when'} eq 'before' ? 'before' : 'after'; return $self; } sub subreport_start { my ( $self, $name, $attr ) = @_; $self->SUPER::subreport_start( $name, $attr ); $self->{'lrc_row_idx_stack'} = []; return; } sub subreport_end { my ( $self, $name ) = @_; $self->SUPER::subreport_end( $name ); die "subreport_end(): assertion failed: row_idx_stack should be empty" if @{$self->{'lrc_row_idx_stack'}}; delete $self->{'lrc_row_idx_stack'}; delete $self->{'lrc_table_summary'}; delete $self->{'lrc_in_table_summary'}; return; } sub table_end { my ( $self, $name ) = @_; $self->handle_table_summary( $self->{'lrc_table_summary'}{'nrecords'}, $self->{'lrc_table_summary'}{'row'} ) if $self->{'lrc_summary_when'} eq 'after'; $self->SUPER::table_end( $name ); return; } sub table_info_end { my ( $self, $name ) = @_; $self->SUPER::table_info_end( $name ); foreach my $row ( @{ $self->current_table_info()->header_rows() } ) { $self->handle_header_row( $row ); } return; } sub group_summary_start { my ( $self, $name, $attr ) = @_; $self->SUPER::group_summary_start( $name, $attr ); if ( defined $attr->{'row-idx'} ) { push @{$self->{'lrc_row_idx_stack'}}, $attr->{'row-idx'}; } elsif ( ! $self->within_element( "lire:group" ) ) { $self->{'lrc_in_table_summary'} = 1; $self->{'lrc_table_summary'} = { 'nrecords' => $attr->{'nrecords'}, 'row' => [], }; } return; } sub group_summary_end { my ( $self, $name ) = @_; $self->SUPER::group_summary_end( $name ); if ( $self->{'lrc_in_table_summary'} ) { $self->{'lrc_in_table_summary'} = 0; $self->handle_table_summary( $self->{'lrc_table_summary'}{'nrecords'}, $self->{'lrc_table_summary'}{'row'} ) if $self->{'lrc_summary_when'} eq 'before'; } else { pop @{$self->{'lrc_row_idx_stack'}}; } } sub entry_start { my ( $self, $name, $attr ) = @_; $self->SUPER::entry_start( $name, $attr ); push @{$self->{'lrc_row_idx_stack'}}, $attr->{'row-idx'}; $self->{'lrc_curr_entry'} = {} unless ( $self->within_element( 'lire:group' ) ); } sub entry_end { my ( $self, $name) = @_; $self->SUPER::entry_end( $name ); my $row_idx = pop @{$self->{'lrc_row_idx_stack'}}; # Skip extra entry return unless defined $row_idx; # We generate row events only when the entry of the first level # is closed. We are sure that all the row spanned by that entry # are complete return if ( $self->within_element( 'lire:group' ) ); foreach my $idx ( sort { $a <=> $b } keys %{$self->{'lrc_curr_entry'}} ) { $self->handle_row( $self->{'lrc_curr_entry'}->{$idx} ); } return; } sub handle_name { my ( $self, $name ) = @_; # When row_idx is undefined, that cell is part of an # entry which shouldn't be displayed. my $row_idx = $self->curr_row_idx(); return unless defined $row_idx; my $col = $name->{'col_info'}->col_start(); $self->{'lrc_curr_entry'}{$row_idx}[$col] = $name; return; } sub handle_value { my ( $self, $value ) = @_; # When row_idx is undefined, that cell is part of an # entry which shouldn't be displayed. my $row_idx = $self->curr_row_idx(); return unless defined $row_idx; my $col = $value->{'col_info'}->col_start(); $self->{'lrc_curr_entry'}{$row_idx}[$col] = $value; return; } sub handle_summary_value { my ( $self, $value ) = @_; # Mark it as a summary value $value->{'is_summary'} = 1; my $col = $value->{'col_info'}->col_start(); if ( $self->{'lrc_in_table_summary'} ) { $self->{'lrc_table_summary'}{'row'}[$col] = $value; } else { # When row_idx is undefined, that cell is part of an # entry which shouldn't be displayed. my $row_idx = $self->curr_row_idx(); return unless defined $row_idx; $self->{'lrc_curr_entry'}{$row_idx}[$col] = $value; } return; } sub curr_row_idx { $_[0]{'lrc_row_idx_stack'}[$#{$_[0]{'lrc_row_idx_stack'}}]; } =pod =head2 handle_table_summary( $nrecords, $row ) Called after the table summary is available (and depending on the C initialisation parameter). $nrecords contains the number of records used to compute the report and $row is an array reference to the table summary value. The $row array contains as much elements as there is columns in the table. Only the numerical column will have a value in there, others will be set to undef. The summary value are hash reference containing the same values than is available in the Lire::ReportParser's handle_summary_value() event. =cut sub handle_table_summary { my ( $self, $nrecords, $row ) = @_; } =pod =head2 handle_header_row( $row ) This will called once for each header row there is. The first header row contains all the numerical columns as well as the main categorical column. $row is an array reference containing as much element as there is columns in the table. Column's labels which shouldn't appear on this row are undef. Other elements will contain the related Lire::Report::ColumnInfo object. =cut sub handle_header_row { my ( $self, $row ) = @_; } =pod =head2 handle_row( $row ) This event will be called for each row to display in the table. $row is an array reference containing the data that should appear in the row. It contains as many elements as there are columns defined in the table. Empty column will have undef as content. Other elements will be an hash reference identical to what would be received in the handle_name() or handle_value() method of Lire::ReportParser. The only difference is that summary value will have a key C set to 1. In the case of spanning columns, the data element will be in the col_start() element. The other cells will be undef. =cut sub handle_row { my ( $self, $row ) = @_; } 1; __END__ =head1 SEE ALSO Lire::ReportParser(3pm) Lire::Report::ColumnInfo(3pm) =head1 VERSION $Id: RowColHandler.pm,v 1.13 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/ReportParser/AsciiDocBookFormatter.pm0000644000175000017500000003427310460673257020766 00000000000000package Lire::ReportParser::AsciiDocBookFormatter; use strict; use base qw/ Exporter Lire::DocBookParser /; use Text::Wrap qw/ wrap /; use Lire::Utils qw/deep_copy/; use Lire::I18N qw/ensure_utf8 ensure_local_codeset/; our @EXPORT_OK = qw/dbk2txt/; =pod =head1 NAME Lire::ReportParser::AsciiDocBookFormatter - Lire::ReportParser subclass which formats description. =head1 SYNOPSIS To format DocBook: use Lire::ReportParser::AsciiDocBookFormatter qw/dbk2txt/; my $txt = dbk2txt( "Test" ); In XML Report processors : package MyParser; use base qw/ Lire::ReportParser::AsciiDocBookFormatter Lire::ReportParser /; sub new { my $self = shift->SUPER::new( @_ ); $self->init_docbook_formatter( @_ ); return $self; } sub handle_description { my ( $self, $desc ) = @_; print $desc; return; } =head1 DESCRIPTION This package implements methods that can handle the content of C elements and it can be used by a subclass of Lire::ReportParser. Client only have to inherit from this module so that a handle_description() method is available to process the text formatted DocBook description. This module also provide a convenient dbk2txt() function which can be used to format a string containing DocBook elements into an ASCII equivalent. =head1 USING Lire::ReportParser::AsciiDocBookFormatter Lire::ReportParser processors that would like to work with text version of the description should inherit from Lire::ReportParser::AsciiDocBookFormatter in addition to Lire::ReportParser. If they override the description_start(), description_end()methods, they B link to their parents' version using C. Additionnally, they should merge the value elements_spec() in their elements_spec() implementation. The Lire::ReportParser::AsciiDocBookFormatter should be listed before Lire::ReportParser in the @ISA. The AsciiDocBookFormatter doesn't inherit directly from Lire::ReportParser so that it can be used in multiple inheritance scenario. The subclass should call the init_docbook_formatter() method from their constructor method to initialize the DocBookFormatter module. =head2 init_docbook_formatter( %params ) The initializer recognizes some parameters that can be used to control the behavior of the DocBook handling: =over 4 =item columns The number of columns in which the DocBook text should be formatted. Defaults to 72. =back =cut sub new { my $self = shift->SUPER::new( @_ ); $self->init_docbook_formatter( @_ ); return $self; } sub init_docbook_formatter { my ($self, %args) = @_; $self->{'dbk_columns'} = $args{'columns'} || 72; return $self; } =pod =head2 dbk_start_processing() Initializes the parser's structure for formatting DocBook XML as ASCII. This is used from the description_start implementation. =cut sub dbk_start_processing { my $self = $_[0]; $self->{'dbk_process'} = 1; $self->{'dbk_text'} = ""; $self->{'dbk_text_blocks'} = []; $self->{'dbk_lists'} = []; $self->{'dbk_left_margin'} = 4; $self->{'dbk_right_margin'} = 8; return; } =pod =head2 dbk_end_processing() Cleans the parser structure. This is used from the description_end() implementation. =cut sub dbk_end_processing { my $self = $_[0]; delete $self->{'dbk_process'}; delete $self->{'dbk_text'}; delete $self->{'dbk_text_blocks'}; delete $self->{'dbk_lists'}; return; } sub namespaces { my $self = $_[0]; return { "http://www.logreport.org/LRML/" => 'lire' }; } sub elements_spec { my $self = $_[0]; my $spec = deep_copy( $self->Lire::DocBookParser::elements_spec() ); foreach my $admon ( qw/note tip caution important warning/ ) { $spec->{$admon}{'start'} = 'admonition_start'; $spec->{$admon}{'end'} = 'admonition_end'; } foreach my $element ( keys %$spec ) { next if $element eq 'ulink'; $spec->{$element}{'char'} = 'inline_char' if exists $spec->{$element}{'char'}; } $spec->{'lire:description'} = [ @Lire::DocBookParser::top_levels ]; return $spec; } sub description_start { $_[0]->dbk_start_processing(); return; } sub description_end { my $self = $_[0]; return unless $self->{'dbk_process'}; $self->handle_description( $self->{'dbk_text'} ); $self->dbk_end_processing(); return; } =pod =head2 handle_description( $description ) This method is invoked after the closing tag of the C element is encountered. The $description contains the description formatted in plain text. =cut sub handle_description { $_[0]{'saved_dbk'} = $_[1]; return; } sub parse_end { return $_[0]{'saved_dbk'}; } sub parent_block { return undef unless @{$_[0]{'dbk_text_blocks'}} > 1; return $_[0]{'dbk_text_blocks'}[$#{$_[0]{'dbk_text_blocks'}} - 1]; } sub current_block { return undef unless @{$_[0]{'dbk_text_blocks'}}; return $_[0]{'dbk_text_blocks'}[$#{$_[0]{'dbk_text_blocks'}}]; } sub print_block { my $self = $_[0]; my $block = $self->current_block(); return unless $block; return unless length $block->{'dbk_text'}; my $margin = ' ' x $self->{'dbk_left_margin'}; my $initial = $margin . $block->{'dbk_initial_indent'}; my $next = $margin . $block->{'dbk_indent'}; # Squash space and trim the string. $block->{'dbk_text'} =~ tr/\n\t / /s; $block->{'dbk_text'} =~ s/^\s*//; $block->{'dbk_text'} =~ s/\s*$//; return if $block->{'dbk_text'} =~ /^\s*$/; local $Text::Wrap::columns = $self->{'dbk_columns'} - $self->{'dbk_right_margin'}; $self->{'dbk_text'} .= wrap( $initial, $next, $block->{'dbk_text'} ); if ( $block->{'dbk_skip_line'} ) { $self->{'dbk_text'} .= "\n\n"; } else { $self->{'dbk_text'} .= "\n"; } # Flush text buffer $block->{'dbk_text'} = ""; return; } sub inline_char { my ( $self, $str ) = @_; my $block = $self->current_block(); $block->{'dbk_text'} .= $str if $block; return; } sub start_block { my ( $self, $left_margin_indent, $right_margin_indent )= @_; $left_margin_indent ||= 0; $right_margin_indent ||= 0; # Flush the current block, if there is one $self->print_block(); $self->{'dbk_left_margin'} += $left_margin_indent; $self->{'dbk_right_margin'} += $right_margin_indent; push @{$self->{'dbk_text_blocks'}}, { 'dbk_text' => "", 'dbk_initial_indent' => '', 'dbk_indent' => '', 'dbk_left_margin_indent' => $left_margin_indent, 'dbk_right_margin_indent' => $right_margin_indent, 'dbk_skip_line' => 1, 'dbk_children' => 0, }; my $parent = $self->parent_block(); $parent->{'dbk_children'}++ if $parent; return $self->current_block(); } sub end_block { my $self = $_[0]; # Flush the current block, if there is one $self->print_block(); my $block = $self->current_block(); $self->{'dbk_left_margin'} -= $block->{'dbk_left_margin_indent'}; $self->{'dbk_right_margin'} -= $block->{'dbk_right_margin_indent'}; pop @{$self->{'dbk_text_blocks'}}; return; } sub current_list { return undef unless @{$_[0]{'dbk_lists'}}; return $_[0]{'dbk_lists'}[$#{$_[0]{'dbk_lists'}}]; } sub start_list { my ( $self, $type, %attr )= @_; my $block = $self->start_block( 2 ); push @{$self->{'dbk_lists'}}, { 'dbk_type' => $type, %attr, }; return $self->current_list(); } sub end_list { my $self = $_[0]; $self->end_block(); my $list = pop @{$self->{'dbk_lists'}}; # We need an extra newline when the spacing was set to compact. # Otherwise the next block will start on the line immediately following # the last listitem. $self->{'dbk_text'} .= "\n" if ( $list->{'spacing'} eq 'compact' ); return; } sub dbk_para_start { my ( $self, $name, $attr ) = @_; my $block = $self->start_block(); if ( $self->in_element( "listitem" ) ) { my $parent = $self->parent_block(); my $list = $self->current_list(); $block->{'dbk_skip_line'} = 0 if $list->{'spacing'} eq 'compact'; # Copy listitem indent and initial_indent attribute if ( $parent->{'dbk_children'} == 1 ) { $block->{'dbk_initial_indent'} = $parent->{'dbk_initial_indent'}; } else { # Add extra space before the paragraph if it wasn't the first # and the list is compact $self->{'dbk_text'} .= "\n" if $parent->{'dbk_children'} > 1 && $list->{'spacing'} eq 'compact'; # Put mark only on first para $block->{'dbk_initial_indent'} = $parent->{'dbk_indent'}; } $block->{'dbk_indent'} = $parent->{'dbk_indent'}; } return; } sub dbk_para_end { $_[0]->end_block(); return; } sub dbk_itemizedlist_start { my ( $self, $name, $attr )= @_; $self->start_list( 'itemized', 'mark' => '-', 'spacing' => 'normal', %$attr ); return; } sub dbk_itemizedlist_end { $_[0]->end_list(); return; } sub dbk_orderedlist_start { my ( $self, $name, $attr )= @_; $self->start_list( 'ordered', 'spacing' => 'normal', %$attr, 'item_count' => 0 ); return; } sub dbk_orderedlist_end { $_[0]->end_list(); return; } sub dbk_variablelist_start { my ( $self, $name, $attr )= @_; $self->start_list( 'variable', 'spacing' => 'normal', %$attr ); return; } sub dbk_variablelist_end { $_[0]->end_list(); return; } sub dbk_term_start { my ( $self, $name, $attr )= @_; my $block = $self->start_block(); $block->{'dbk_skip_line'} = 0; return; } sub dbk_term_end { $_[0]->end_block(); return; } sub dbk_listitem_start { my ( $self, $name, $attr )= @_; my $list = $self->current_list(); my $block = $self->start_block(); if ( $list->{'dbk_type'} eq 'itemized' ) { my $mark = $attr->{'override'} || $list->{'mark'}; $block->{'dbk_initial_indent'} = $mark . ' '; $block->{'dbk_indent'} = ' ' x length $block->{'dbk_initial_indent'}; } elsif ( $list->{'dbk_type'} eq 'ordered' ) { $list->{'dbk_item_count'}++; $block->{'dbk_initial_indent'} = $list->{'dbk_item_count'} . '. '; $block->{'dbk_initial_indent'} .= ' ' if length $block->{'dbk_initial_indent'} < 4 ; $block->{'dbk_indent'} = ' ' x length $block->{'dbk_initial_indent'}; } elsif ( $list->{'dbk_type'} eq 'variable' ) { $block->{'dbk_initial_indent'} = ' ' x 4; $block->{'dbk_indent'} = ' ' x 4; } else { warn( "unknown list type: $list->{'dbk_type'}" ); } $block->{'dbk_skip_line'} = 0 if $list->{'spacing'} eq 'compact'; return; } sub dbk_listitem_end { $_[0]->end_block(); return; } sub dbk_title_start { my ( $self, $name, $attr )= @_; $self->start_block( 0, 4 ); return; } sub dbk_title_end { $_[0]->end_block(); return; } sub dbk_ulink_start { my ( $self, $name, $attr )= @_; $self->{'dbk_curr_url_attr'} = $attr->{'url'} || ""; $self->{'dbk_curr_url'} = ""; return; } sub dbk_ulink_end { my $self = $_[0]; $self->inline_char( ' (' . $self->{'dbk_curr_url_attr'} . ')' ) if ( $self->{'dbk_curr_url_attr'} ne $self->{'dbk_curr_url'} ); delete $self->{'dbk_curr_url_attr'}; delete $self->{'dbk_curr_url'}; return; } sub dbk_ulink_char { my ( $self, $str )= @_; $self->inline_char( $str ); $self->{'dbk_curr_url'} .= $str; return; } sub dbk_quote_start { my ( $self, $name, $attr )= @_; $self->inline_char( '"' ); return; } sub dbk_quote_end { my $self = $_[0]; $self->inline_char( '"' ); return; } sub admonition_start { my ( $self, $name, $attr ) = @_; my $block = $self->start_block(); $block->{'dbk_skip_line'} = 0; $self->inline_char( ucfirst $name . ":" ); $self->end_block(); $self->start_block( 2 ); return; } sub admonition_end { $_[0]->end_block(); return; } =pod =head1 FORMATTING DocBook STRINGS If you have DocBook content in a string, like you can obtain from some of the Report Specifications object, you can format it in plain text using the dbx2txt() function. =head2 dbk2txt( $docbook_str, [$columns] ) Returns a plain text version of the DocBook XML fragment $docbook_str. The C parameter sets the number of columns in which the DocBook text should be formatted. This method will die() in case of error. =cut sub dbk2txt { my ( $docbook_str, $columns ) = @_; my $parser = new Lire::ReportParser::AsciiDocBookFormatter( 'columns' => $columns ); return ensure_local_codeset( $parser->parse( '' . '' . ensure_utf8( $docbook_str ) . '' ) ); } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportParser(3pm) =head1 VERSION $Id: AsciiDocBookFormatter.pm,v 1.13 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/LrCommand.pm0000644000175000017500000005734110460673255014034 00000000000000package Lire::LrCommand; use strict; use Lire::Config; use Lire::Config::Build qw/ac_info/; use Lire::ReportConfig; use Lire::PluginManager; use Lire::DlfStore; use Lire::ImportJob; use Lire::OutputJob; use Lire::DlfConverterProcess; use Lire::Utils qw/check_param check_object_param tempdir/; use Lire::Error qw/file_not_writable file_not_readable/; use File::Path qw/rmtree/; use POSIX qw/:locale_h/; use File::Basename; use File::Copy qw/copy/; use Locale::TextDomain 'lire'; use Text::Wrap qw/ wrap /; use Carp; use Getopt::Long; =pod =head1 NAME Lire::LrCommand - Base class for command line programs. =head1 SYNOPSIS my $prog = new Lire::LrCommand(); $prog->init(); $prog->add_section( 'myprog', __( 'My Program Options' ) ); $prog->add_option( 'name' => 'myoption', 'type' => '=s', 'help' => __( 'My option help.' ) ); $prog->add_common_options(); $prog->parse_options(); =head1 DESCRIPTION Class which is used to create command line program which shares functionaliy. =head1 METHODS =head2 new( [$usage], [$help] ) Creates a new Lire::LrCommon instance. Initializes the usage string and the help message to $usage and $help. =cut sub new { my ( $class, $usage, $help ) = @_; my $self = bless {}, $class; $self->{'_prog'} = basename( $0 ); $self->{'_options'} = {}; $self->{'_sections'} = []; $self->{'_section_labels'} = {}; $self->{'_cfg'} = {}; $self->{'_usage'} = $usage || ''; $self->{'_help'} = $help || ''; return $self; } sub init { my $self = $_[0]; setlocale( LC_ALL, '' ); $SIG{'__WARN__'} = sub { $self->warning( @_ ); }; foreach my $name ( qw|.lire .lire/converters .lire/plugins .lire/reports .lire/filters .lire/schemas .lire/templates| ) { my $dir = "$ENV{'HOME'}/$name"; unless ( -d $dir ) { mkdir $dir or $self->error( __x( 'Cannot create directory {directory}.', 'directory' => $dir ) ); $self->info( __x( 'Created {directory}.', 'directory' => $dir ) ); } } Lire::Config->init(); Lire::PluginManager->register_default_plugins(); $self->{'_tmpdir'} = tempdir( $self->{'_prog'} . '_XXXXXX' ); $self->{'_keepdir'} = Lire::Config->get( 'lr_keep' ); $SIG{'PIPE'} = 'IGNORE'; return; } sub DESTROY { my $self = $_[0]; if ( $self->{'_keepdir'} ) { $self->info( __x( 'Keeping temporary directory {tmpdir}', 'tmpdir' => $self->{'_tmpdir'} ) ); } else { rmtree( $self->{'_tmpdir'} ); } return; } =pod =head2 set_usage( [$usage] ) =cut sub set_usage { my ( $self, $usage ) = @_; $self->{'_usage'} = $usage; return; } =pod =head2 set_help( [$help] ) =cut sub set_help { my ( $self, $help ) = @_; $self->{'_help'} = $help; return; } =pod =head2 set_section( [$name], [$label] ) =cut sub add_section { my ( $self, $name, $label ) = @_; check_param( $name, 'name' ); check_param( $label, 'label' ); push @{$self->{'_sections'}}, $name; $self->{'_section_labels'}{$name} = $label; return; } =pod =head2 add_option( [%args] ) =cut sub add_option { my ( $self, %args ) = @_; check_param( $args{'name'}, 'name' ); check_param( $args{'section'}, 'section' ); my $section = $args{'section'}; croak "invalid section: $section" unless exists $self->{'_section_labels'}{$section}; check_param( $args{'help'}, 'help' ); check_object_param( $args{'aliases'}, 'aliases', 'ARRAY' ) if defined $args{'aliases'}; $args{'aliases'} = [] unless defined $args{'aliases'}; $args{'type'} = '' unless defined $args{'type'}; $args{'action'} = 'store' unless defined $args{'action'}; $self->{'_options'} ||= []; push @{$self->{'_options'}{$section}}, \%args; return; } =pod =head2 add_common_options() =cut sub add_common_options { my $self = $_[0]; $self->add_section( 'common', __( 'Common options' ) ); $self->add_option( 'name' => 'help', 'type' => ':s', 'section' => 'common', 'action' => sub { $self->do_help( $_[1] ) }, 'help' => __( 'Print usage information and exit. If "report-templates", "output-formats" or "dlf-converters" is given as argument, the command will print an information list for that object type.' ), ); $self->add_option( 'name' => 'version', 'section' => 'common', 'action' => sub { $self->do_version() }, 'help' => __( 'Print Lire version and exit.' ), ); $self->add_option( 'name' => 'quiet', 'type' => '!', 'section' => 'common', 'help' => __( 'Only print errors.' ), ); return; } sub add_email_options { my $self = $_[0]; $self->add_section( 'email', __( 'Email related options' ) ); $self->add_option( 'name' => 'subject', 'section' => 'email', 'help' => __( "Sets the email's subject." ), 'type' => '=s' ); $self->add_option( 'name' => 'extra-file', 'type' => '=s', 'section' => 'email', 'help' => __( 'A text file that will be included with the report.' ), ); return; } sub add_output_format_options { my $self = $_[0]; $self->add_section( 'output', __( 'Output format options' ) ); $self->add_option( 'name' => 'image', 'section' => 'output', 'help' => __( 'Backward compatibility.' ), 'obsolete' => 1 ); $self->add_option( 'name' => 'output-format', 'type' => '=s', 'section' => 'output', 'help' => __( 'Select the output format. Default to "txt"' ), ); return; } sub add_merging_options { my $self = $_[0]; $self->add_section( 'merging', __( 'Merging options' ) ); $self->add_option( 'name' => 'template', 'section' => 'merging', 'type' => '=s', 'help' => __( 'Select the report configuration template that should be used for merging the reports. This option is required if you use the --merge option.' ), ); $self->add_option( 'name' => 'merge', 'section' => 'merging', 'aliases' => [ 'x' ], 'type' => '=s@', 'help' => __( 'Merge an additional report before formatting the report. This option can be used multipe times.' ), ); $self->add_option( 'name' => 'report-cfg', 'type' => '=s', 'section' => 'merging', 'aliases' => [ 'c' ], 'help' => __( 'Pre Lire 2.0 report configuration file.' ), 'obsolete' => 1 ); $self->add_option( 'name' => 'U', 'type' => '=s', 'section' => 'merging', 'help' => __( 'Selects the superservice for which the report configuration file is made.' ), 'obsolete' => 1 ); return; } sub add_report_options { my $self = $_[0]; $self->add_section( 'report', __( 'Report generation options' ) ); $self->add_option( 'name' => 'report-cfg', 'type' => '=s', 'section' => 'report', 'aliases' => [ 'c' ], 'help' => __( 'Pre Lire 2.0 report configuration file.' ), 'obsolete' => 1 ); $self->add_option( 'name' => 'template', 'section' => 'report', 'type' => '=s', 'help' => __( 'Select the report configuration template that should be used for generating the report.' ), ); return; } sub get_option { my ( $self, $name, $default ) = @_; check_param( $name, 'name' ); return defined $self->{'_cfg'}{$name} ? $self->{'_cfg'}{$name} : $default; } sub parse_options { my $self = $_[0]; my @options = (); foreach my $section ( @{$self->{'_sections'}} ) { foreach my $opt ( @{$self->{'_options'}{$section}} ) { my $spec = join ( "|", $opt->{'name'}, @{$opt->{'aliases'}} ) . $opt->{'type'}; $self->{'_cfg'}{$opt->{'name'}} = $opt->{'action'} if ref $opt->{'action'}; push @options, $spec; } } GetOptions( $self->{'_cfg'}, @options ) or $self->usage(); return; } sub error { my ( $self, @msgs ) = @_; print STDERR $self->{'_prog'} . ': ' . __( 'ERROR ' ), join( "\n", @msgs ), "\n"; exit(1); } sub warning { my ( $self, @msgs ) = @_; return if $self->{'_cfg'}{'quiet'}; print STDERR $self->{'_prog'} . ': ' . __( 'WARNING ' ), join( "\n", @msgs ), "\n"; return; } sub info { my ( $self, @msgs ) = @_; return if $self->{'_cfg'}{'quiet'}; print STDERR join( "\n", @msgs ), "\n"; return; } sub do_version { my $self = $_[0]; print STDERR __x( '{program} as shipped with Lire version {version}', 'program' => $self->{'_prog'}, 'version' => ac_info( 'VERSION' ) ), "\n"; exit(0); } sub usage { my ( $self, $msg ) = @_; if ( $msg ) { chomp $msg; print STDERR $msg, "\n" if $msg; } $self->print_usage(); exit(1); } sub print_usage { my $self = $_[0]; print STDERR __x( 'Usage: {program} {usage}', 'program' => $self->{'_prog'}, 'usage' => $self->{'_usage'} ), "\n"; return; } sub do_help { my ( $self, $section ) = @_; $section ||= ''; if ( $section eq 'output-formats' ) { $self->do_help_output_formats(); } elsif ( $section eq 'report-templates' ) { $self->do_help_report_templates(); } elsif ( $section eq 'dlf-converters' ) { $self->do_help_dlf_converters(); } elsif ( $section ) { print STDERR __x( 'Unknown help section: {section}', 'section' => $section ), "\n"; } $self->print_usage(); print STDERR "\n", wrap( '', '', $self->{'_help'} ), "\n", "\n"; foreach my $section ( @{$self->{'_sections'} } ) { print STDERR uc $self->{'_section_labels'}{$section}, "\n"; foreach my $option ( @{$self->{'_options'}{$section}} ) { my $obsolete = $option->{'obsolete'} ? ' ' . __( 'This option is obsolete.' ) : ''; print wrap( sprintf( ' --%-17s', $option->{'name'} ) . ' ', ' ' x 22, $option->{'help'} . $obsolete ), "\n"; } print "\n"; } exit(0); } sub do_help_report_templates { my $self = $_[0]; print STDERR __( 'Available report templates:' ), "\n"; foreach my $template ( sort @{Lire::ReportConfig->templates()} ) { print STDERR $template, "\n"; } exit(0); } sub do_help_dlf_converters { my $self = $_[0]; print STDERR __( 'Available DLF converters:' ), "\n"; my @plugins = sort { $a->name() cmp $b->name() } @{Lire::PluginManager->plugins( 'dlf_converter' )}; foreach my $converter ( @plugins ) { printf STDERR "%-16s %s\n", $converter->name(), $converter->title(); } exit(0); } sub do_help_output_formats { my $self = $_[0]; print STDERR __( 'Available output formats:' ), "\n"; my @plugins = sort { $a->name() cmp $b->name() } @{Lire::PluginManager->plugins( 'output_format' )}; foreach my $format ( @plugins ) { printf STDERR "%-16s %s\n", $format->name(), $format->title(); } exit(0); } sub init_temp_store { my $self = $_[0]; $self->{'_store'} = eval { Lire::DlfStore->open( "$self->{'_tmpdir'}/store", 1 ); }; $self->error( $@ ) if $@; return; } sub is_compressed { my ( $self, $magic ) = @_; return unless length $magic; if ( substr($magic,0,2) eq "\037\235" ) { return 'compress'; } elsif ( substr($magic,0,2) eq "\037\213" ) { return 'gzip'; } elsif ($magic eq "PK\003\004" ) { return 'PKZIP'; } return; } sub handle_logfile { my ( $self, $logfile ) = @_; $self->{'_logfile'} = $logfile; open my $fh, $logfile or $self->error( file_not_readable( $logfile ) ); my $magic; read $fh, $magic, 4; $self->error( __x( 'read failed: {error}', 'error' => $! ) ) unless defined $magic; my $algo = $self->is_compressed( $magic ); my $tmplogfile = "$self->{'_tmpdir'}/logfile"; my $out_fh; if ( $algo ) { $self->info( __x( 'Log file was compressed using {algo}.', 'algo' => $algo ) ); $self->error( __( "gzip(1) isn't available" ) ) unless Lire::Config->get_var( 'gzip_path' )->is_valid(); my $gzip = Lire::Config->get( 'gzip_path' ); $self->info( __x( 'Decompressing log file using {gzip}...', 'gzip' => $gzip ) ); local %ENV = (); open $out_fh, "|$gzip -d > $tmplogfile" or $self->error( __x( 'error forking: {error}', 'error' => $! ) ); } elsif ( $logfile eq '-' or $logfile =~ /\|\s*$/ ) { open $out_fh, "> $tmplogfile" or $self->error( file_not_writable( $tmplogfile ) ); } if ( $out_fh ) { $self->{'_logfile'} = $tmplogfile; print $out_fh $magic; my $buffer; while ( read $fh, $buffer, 1024**2 ) { print $out_fh $buffer; } $self->error( __x( 'read failed: {error}', 'error' => $! ) ) unless defined $buffer; close $out_fh or $self->error( __x( "gzip exited with non zero status: {status}", 'status' => $? ) ); } close $fh; return; } =pod =head2 import_log( [$converter], [$logfile] ) import_log invokes Lire::ImportJob and Lire::DlfConverterProcess. It uses &handle_logfile. This means that in case the $logfile is compressed, it is decompressed to a file in $TMPDIR. In case the $logfile is read from a pipe or from STDIN, it is written to a file in $TMPDIR. So, if you're short on discspace, pass the logfile as an uncompressed file. =cut sub import_log { my ( $self, $converter, $logfile ) = @_; $self->check_converter( $converter ); $self->handle_logfile( $logfile ); $self->info( __x( 'Parsing log file using {converter} DLF Converter...', 'converter' => $converter ) ); eval { my $src = new Lire::ImportJob( "lr_store", pattern => $self->{'_logfile'}, period => 'unique', converter => $converter ); my $process = new Lire::DlfConverterProcess( $src, $self->{'_store'} ); $process->run_import_job(); $self->info( __x( 'Extracted {dlf_count} DLF records on {line_count} lines.', 'dlf_count' => $process->dlf_count(), 'line_count' => $process->line_count() ) ); $self->info( __x( 'Encountered {error_count} errors and ignored {ignored_count} lines.', 'error_count' => $process->error_count(), 'ignored_count' => $process->ignored_count() ) ); }; $self->error( $@ ) if $@; return; } sub init_report_config { my ( $self, $converter ) = @_; if ( $self->{'_cfg'}{'template'} ) { $self->{'_report_cfg'} = $self->load_report_config_from_template(); } elsif ( $self->{'_cfg'}{'report-cfg'} ) { $self->{'_report_cfg'} = eval { new_from_file Lire::ReportConfig( $self->find_superservice( $converter ), $self->{'_cfg'}{'report-cfg'} ) }; $self->error( $@ ) if $@; } else { my $template = $self->find_superservice( $converter) . '_default'; $self->error( __x( 'No default report configuration template defined for DLF converter "{converter}.".', 'converter' => $converter, 'template' => $template ), __( 'Use the --template option.' ) ) unless Lire::ReportConfig->has_template( $template ); $self->{'_report_cfg'} = Lire::ReportConfig->template( $template )->as_value(); } return; } sub check_converter { my ( $self, $converter ) = @_; $self->error( __x( 'No such DLF converter: {converter}.', 'converter' => $converter ), __( 'Use --help dlf-converters to list available converters' ) ) unless Lire::PluginManager->has_plugin( 'dlf_converter', $converter ); return; } sub find_superservice { my ( $self, $converter ) = @_; $self->check_converter( $converter ); my $plugin = Lire::PluginManager->get_plugin( 'dlf_converter', $converter); return ($plugin->schemas())[0]; } =pod =head2 generate_report( [$converter], [$logfile] ) Generate a report from a $logfile, using $converter. Returns $reportfile. Uses Lire::ReportConfig::generate_report to do the real work. =cut sub generate_report { my ( $self, $converter, $logfile ) = @_; check_param( $converter, 'converter' ); check_param( $logfile, 'logfile' ); $self->init_temp_store(); $self->init_report_config( $converter ); $self->import_log( $converter, $logfile ); $self->info( __( 'Running analysers...' ) ); my $cfg = $self->{'_report_cfg'}; eval { $cfg->create_analyser_streams( $self->{'_store'} ) }; $self->error( $@ ) if $@; $self->info( __( 'Generating XML report...' ) ); my $report = eval { $cfg->generate_report( $self->{'_store'} ) }; $self->error( $@ ) if $@; my $reportfile = "$self->{'_tmpdir'}/report.xml"; open my $fh, "> $reportfile" or $self->error( file_not_writable( $reportfile ) ); eval { $report->write_report( $fh ); $fh->close(); }; $self->error( $@ ) if $@; return $reportfile; } sub load_report_config_from_template { my $self = $_[0]; my $name = $self->{'_cfg'}{'template'}; $self->error( __x( 'No report configuration template: {template}.', 'template' => $name ), __( 'Use --help report-templates to list available templates.', ) ) unless Lire::ReportConfig->has_template( $name ); return Lire::ReportConfig->template( $name )->as_value(); } sub init_merging_report_config { my $self = $_[0]; if ( $self->{'_cfg'}{'template'} ) { return $self->load_report_config_from_template(); } elsif ( $self->{'_cfg'}{'report-cfg'} ) { $self->error( __( 'The -U option is required with --report-cfg' ) ) unless $self->{'_cfg'}{'U'}; return eval { new_from_file Lire::ReportConfig( $self->{'_cfg'}{'U'}, $self->{'_cfg'}{'report-cfg'} ) }; $self->error( $@ ) if $@; } else { $self->error( __( 'You need to use the --template option to merge reports.' ) ); } } sub merge_reports { my ( $self, $report ) = @_; return $report unless $self->{'_cfg'}{'merge'}; my @reports = ( $report, @{$self->{'_cfg'}{'merge'}} ); my $cfg = $self->init_merging_report_config(); my $tmpreport = "$self->{'_tmpdir'}/merged-report.xml"; $self->info( __x( "Merging reports '{reports}'...", 'reports' => join "', '", @reports ) ); eval { my $report = $cfg->merge_report_files( @reports ); open my $fh, "> $tmpreport" or $self->error( file_not_writable( $tmpreport ) ); $report->write_report( $fh ); close $fh; }; $self->error( $@ ) if $@; return $tmpreport; } sub check_output_format { my $self = $_[0]; $self->{'_cfg'}{'output-format'} ||= 'txt'; my $format = $self->{'_cfg'}{'output-format'} ||= 'txt'; $self->error( __x( 'No such output format: {format}.', 'format' => $format ), __( 'Use --help output-formats to list available formats.') ) unless Lire::PluginManager->has_plugin( 'output_format', $format ); my $plugin = Lire::PluginManager->get_plugin( 'output_format', $format ); my $missings = join "\n", $plugin->missing_requirements(); $self->error( __( 'This output format has missing requirements:' ), $missings ) if $missings; return; } sub format_report { my ( $self, $report_file, $output_file ) = @_; check_param( $report_file, 'report_file' ); check_param( $output_file, 'output_file' ); eval { my $format = $self->{'_cfg'}{'output-format'}; $self->info( __x( 'Formatting report as {format} in {file}...', 'format' => $format, 'file' => $output_file ) ); my $stdout = 0; if ( $output_file eq '-' or $output_file =~ /\|\s*/ ) { $output_file = "$self->{'_tmpdir'}/formatted-report.$format"; $stdout = 1; } my $job = new Lire::OutputJob( 'file', Lire::PluginManager->get_plugin( 'output_format', $format ), {}, 'file' => $output_file ); $job->run( $report_file ); if ( $format eq 'html' && $stdout ) { my $tar = Lire::Config->get( 'tar_path' ); system ( "$tar cC $self->{'_tmpdir'} report" ); } elsif ( $stdout ) { copy( $output_file, \*STDOUT ); } }; $self->error( $@ ) if $@; return; } sub check_email_requirements { my $self = $_[0]; eval "use MIME::Entity;"; $self->error( __( 'This command requires the MIME::Tools CPAN module.' ) ) if $@; return; } sub email_report { my ( $self, $report_file, @emails ) = @_; check_param( $report_file, 'report_file' ); eval { my $format = $self->{'_cfg'}{'output-format'}; my $subject = $self->{'_cfg'}{'subject'} || __x( 'Your {format} report.', 'format' => $format ); $self->info( __x( 'Formatting report as {format} and emailing it to {emails}...', 'format' => $format, 'emails' => join( ", ", @emails ) ), ); my $plugin = Lire::PluginManager->get_plugin( 'output_format', $format ); my $job = new Lire::OutputJob( 'email', $plugin, {}, 'subject' => $subject, 'extra_file' => $self->{'_cfg'}{'extra-file'}, 'emails' => \@emails ); $job->run( $report_file ); }; $self->error( $@ ) if $@; return; } 1; __END__ =pod =head1 SEE ALSO lr_log2report(1), lr_log2mail(1), lr_xml2mail(1), lr_xml2report(1), Lire::Config(3pm), Lire::ReportConfig(3pm), Lire::PluginManager(3pm), Lire::DlfStore(3pm), Lire::ImportJob(3pm), Lire::OutputJob(3pm), Lire::DlfConverterProcess(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: LrCommand.pm,v 1.9 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogRepor t.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Max.pm0000644000175000017500000000453010765035043012670 00000000000000package Lire::Max; use strict; use base qw/ Lire::SimpleStat /; use Carp; use Lire::Utils qw/ sql_quote_name /; =pod =head1 NAME Lire::Max - Lire class that implements the max operator =head1 SYNOPSIS use Lire::Max =head1 DESCRIPTION Class that implements the max operator. This operator will find the minimum value appearing in a DLF field among a group of DLF records. =head1 METHODS =head2 new( %params ) Creates a new Lire::Max object. =cut sub new { my $self = bless {}, shift; $self->init( @_, 'op' => 'max' ); return $self; } # Implements Lire::Aggregate::sql_aggr_expr sub sql_aggr_expr { my $self = $_[0]; return 'max(' . sql_quote_name( $self->{'field'} ) . ')'; } # Implements Lire::ReportOperator::init_group_data sub init_group_data { my $scalar = undef; return \$scalar; } # Implements Lire::ReportOperator::merge_group_data sub merge_group_data { my ( $self, $value, $data ) = @_; return if lc $value->{'value'} eq 'nan'; $$data = $value->{'value'} unless ( defined $$data ); # To merge two max, we keep the highest $$data = $value->{'value'} if $value->{'value'} > $$data; return; } # Implements Lire::ReportOperator::end_group_data sub end_group_data { my ( $self, $data ) = @_; $$data = "NaN" unless defined $$data; return; } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::ReportOperator(3pm), Lire::Aggregator(3pm), Lire::Aggregate(3pm). =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: Max.pm,v 1.10 2008/03/09 19:27:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001, 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Average.pm0000644000175000017500000002455010765035042013520 00000000000000package Lire::Average; use strict; use base qw/ Lire::SimpleStat /; use Carp; use Lire::DataTypes qw/ is_numeric_type format_numeric_type /; use Lire::Utils qw/ sql_quote_name check_object_param/; use Lire::ReportOperator qw/group_data_value/; use Lire::Count; use Lire::Sum; =pod =head1 NAME Lire::Average - Lire class that implements the avg operator =head1 SYNOPSIS use Lire::Average =head1 DESCRIPTION Class that implements the avg operator. This operator will compute the average value of a DLF field in a group of DLF records. If the field used by average isn't a numeric fields, the number of different values in that field will be used as the numerator. It's possible to compute a weighted average by specifying a weighting field. By default, the average is a by record average. It's possible to compute a by different values average. The list of fields that's used to determine the different values if speficied in the by-fields attribute. =head1 METHODS =head2 new( %params ) Creates a new Lire::Average object. In addition to the values supported by its parents, the by-fields and weight attributes will be initialized to the values specified in the %params argument. =cut sub new { my $self = bless {}, shift; $self->init( @_, 'op' => "avg" ); my %args = @_; $self->by_fields( $args{'by-fields'} ) if exists $args{'by-fields'}; $self->weight( $args{'weight'} ) if exists $args{'weight'}; return $self; } #------------------------------------------------------------------------ # Method field( [$field] # # Overrides Lire::SimpleStat one since the field doesn't have # to be numeric. sub field { my ($self, $field ) = @_; if ( @_ == 2 ) { if ( defined $field ) { croak "'$field' isn't a defined field in the specification's schemas" unless $self->report_spec()->has_field( $field ); } $self->{'field'} = $field; } $self->{'field'}; } =pod =head2 by_fields( [$new_by_fields] ) Returns the fields that are going to be used to count the different values which will made up the by part of the average. This a reference to an array of DLF field names. If the $new_by_fields parameter is set, it will be used as the new $by_fields value. It must be an array reference and should only contains valid field names for the current report specification's schema. =cut sub by_fields { my ($self, $by_fields) = @_; if ( @_ == 2 ) { if ( defined $by_fields ) { check_object_param( $by_fields, 'by_fields', 'ARRAY' ); foreach my $f ( @$by_fields ) { croak "$f isn't a defined field in the specification's schemas" unless $self->report_spec()->has_field( $f ); } } $self->{'by_fields'} = $by_fields; } $self->{'by_fields'}; } =pod =head2 weigth( [$new_weight] ) Returns the DLF field's name by which the values will be multiplied before being summed. You can change the weight field by specifying a new name as the $new_weight parameter. Use undef to remove the use of a weighting field. =cut sub weight { my ($self, $weight) = @_; if ( @_ == 2 ) { if ( defined $weight ) { croak "'$weight' isn't a defined field in the specification's schemas" unless $self->report_spec()->has_field( $weight ); croak "$weight isn't a numeric type", unless is_numeric_type( $self->report_spec()->field( $weight )->type() ); } $self->{'weight'} = $weight; } $self->{'weight'}; } #------------------------------------------------------------------------ # Method xml_attrs() # # Implementation needed by Lire::Aggregate sub xml_attrs { my ($self) = @_; my $attr = $self->SUPER::xml_attrs; $attr .= qq{ weight="$self->{'weight'}"} if defined $self->{'weight'}; if ( exists $self->{'by_fields'} ) { my $by_fields = join " ", @{$self->{'by_fields'}}; $attr .= qq{ by-fields="$by_fields"}; } $attr; } # Overrides Lire::Aggregate::build_query sub build_query { my ( $self, $query ) = @_; $self->_build_avg_query( $query ); $self->set_missing_cases_aggr_expr( $query ); } sub _build_avg_query { my ( $self, $query ) = @_; my $sum_expr; if ( defined $self->{'weight' }) { $sum_expr = sprintf( 'sum(%s*%s)', sql_quote_name( $self->{'field'} ), sql_quote_name( $self->{'weight'} ) ); } else { $sum_expr = sprintf( 'sum(%s)', sql_quote_name( $self->{'field'} ) ); } $query->add_aggr_field( $self->{'name'} . "_total", $sum_expr ); my $n_expr; if ( !defined $self->{'by_fields'} ) { $n_expr = 'count(*)'; } elsif ( @{$self->{'by_fields'}} == 1 && is_numeric_type( $self->report_spec()->field( $self->{'by_fields'}[0] )->type() ) ) { $n_expr = sprintf( 'sum(%s)', sql_quote_name($self->{'by_fields'}[0])); } else { my @fields = map { sql_quote_name( $_ ) } @{ $self->{'by_fields'} }; $n_expr = sprintf( 'lr_count_uniq(%s)', join (',', @fields) ); } $query->add_aggr_field( $self->{'name'} . "_n", $n_expr ); $query->add_aggr_field( $self->{'name'}, sprintf( '%s/%s', $sum_expr, $n_expr ) ); return; } # Overrides Lire::SimpleStat::sql_required_fields sub sql_required_fields { my $self = $_[0]; my @fields = ( $self->{'field'} ); push @fields, $self->{'weight'} if defined $self->{'weight'}; push @fields, @{ $self->{'by_fields'} } if defined $self->{'by_fields'}; return \@fields; } # Overrides Lire::SimpleStat::create_value sub create_value { my ( $self, $group, $row ) = @_; my %value; my $name = $self->name(); my $avg; if ( ! $row->{$name . "_n"} ) { $avg = 'NaN'; } elsif ( ! $row->{ $name . '_total'} ) { $avg = '0.00'; } else { $avg = sprintf( "%.2f", $row->{$name . '_total' } / $row->{$name . "_n"}); } $value{'content'} = format_numeric_type( $avg, $self->dlf_field()->type() ); $value{'value'} = $avg; $value{'total'} = $row->{ $name . '_total' }; $value{'n'} = $row->{ $name . '_n' }; $self->set_missing_cases_value( $row, \%value ); return \%value; } # Implements Lire::ReportOperator::init_merge sub init_merge { my $self = $_[0]; $self->create_avg_ops(); $self->{'sum_op'}->init_merge(); $self->{'n_op'}->init_merge(); return; } # Initialize n_op and sum_op sub create_avg_ops { my ($self) = @_; my %common = ( 'parent' => $self->parent(), 'report_spec' => $self->report_spec(), ); if ( $self->field() ) { my $f = $self->report_spec()->schema()->field( $self->field ); if ( is_numeric_type( $f->type() ) ) { # Use a sum $self->{'sum_op'} = new Lire::Sum( %common, 'name' => $self->name() . ".sum", 'field' => $self->field(), 'weight' => $self->weight(), ); } else { # Use a counter $self->{'sum_op'} = new Lire::Count( %common, 'fields' => [ $self->field() ], 'name' => $self->name() . ".sum", ); } } else { # Use a simple count operation $self->{'sum_op'} = new Lire::Count( %common, 'name' => $self->name() . ".sum" ); } # Special case for a numerical field. This enables # to compute arbitrary ratio. # FIXME: A new operator ratio operator should be defined if ( $self->by_fields() && @{$self->by_fields()} == 1 && is_numeric_type( $self->report_spec()->schema()->field( $self->by_fields()->[0])->type())) { $self->{'n_op'} = new Lire::Sum( %common, 'field' => $self->by_fields->[0], 'name' => $self->name() . ".n" ); } else { $self->{'n_op'} = new Lire::Count( %common, 'fields' => $self->by_fields(), 'name' => $self->name() . ".n" ); } } # Implements Lire::ReportOperator::init_group_data sub init_group_data { my ( $self ) = @_; # Result is held in the first element return [ "NaN", $self->{'sum_op'}->init_group_data(), $self->{'n_op'}->init_group_data() ]; } # Implements Lire::ReportOperator::merge_group_data sub merge_group_data { my ( $self, $value, $data ) = @_; $self->{'sum_op'}->merge_group_data( {value => $value->{'total'}}, $data->[1] ); $self->{'n_op'}->merge_group_data( {value => $value->{'n'}}, $data->[2] ); return; } # Implements Lire::ReportOperator::end_group_data sub end_group_data { my ( $self, $data ) = @_; $self->{'sum_op'}->end_group_data( $data->[1] ); $self->{'n_op'}->end_group_data( $data->[2] ); my $sum = group_data_value( $data->[1] ); my $n = group_data_value( $data->[2] ); $data->[0] = sprintf "%.2f", $sum / $n if $n; return; } # Implements Lire::ReportOperator::end_merge() sub end_merge { my $self = $_[0]; $self->{'sum_op'}->end_merge(); $self->{'n_op'}->end_merge(); return; } # Implements Lire::Aggregate::data2dlf() sub data2dlf { my ($self, $data) = @_; my $name = $self->name(); return { "$name" => $data->[0], "${name}_total" => group_data_value( $data->[1] ), "${name}_n" => group_data_value( $data->[2] ), "_lr_${name}_mc" => $self->missing_cases( $data ), }; } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::ReportOperator(3pm), Lire::Aggregator(3pm), Lire::Aggregate(3pm). =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 VERSION $Id: Average.pm,v 1.17 2008/03/09 19:27:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/DlfSchema.pm0000644000175000017500000007070110460673254014000 00000000000000package Lire::DlfSchema; use strict; use vars qw/ %SCHEMA_CACHE /; use Carp; use Locale::TextDomain 'lire'; use XML::Parser; use Lire::Config::Build qw/ ac_info /; use Lire::Config; use Lire::DataTypes qw/ check_xml_name check_superservice check_type /; use Lire::Field; use Lire::DerivedSchema; use Lire::ExtendedSchema; use Lire::DlfQuery; use Lire::I18N qw/ bindtextdomain dgettext dgettext_para /; use Lire::Utils qw/ sql_quote_name check_param check_object_param /; BEGIN { %SCHEMA_CACHE = (); }; =pod =head1 NAME Lire::DlfSchema - Interface to Lire DLF Schema XML specifications =head1 SYNOPSIS In DLF converters: use Lire::DlfSchema; my $schema = Lire::DlfSchema::load_schema( "email" ); my $fields = $schema->fields(); my $dlf_id = $schema->field( 'dlf_id' ); my $dlf_src = $schema->field( 'dlf_source' ); =head1 DESCRIPTION This module is the interface to the Lire DLF Schemas defined in XML files. A schema defines the order of the fields along with their names, descriptions and types. Each DlfSchema have at least two predefined fields: =over =item dlf_id This is an integer which uniquely identify a DLF record in its stream. Its used to link the record to its extended schemas fields and also to link the record to the derived schemas records. =item dlf_source This is an identifier which can be used to track the record the ImportJob that created it. =back =head1 ACCESSING A SCHEMA OBJECT The way to access a schema for a superservice is through the load_schema() module function. You use it like this: my $schema = Lire::DlfSchema::load_schema( $superservice); This function will return a schema object which can then be used to query information about the schema. This function will die() on error. =cut sub load_schema { my ( $name ) = @_; check_param ( $name, 'name', \&check_xml_name, 'invalid schema identifier' ); my $super = $name; if ($name =~ /^(\w+)-/ ) { $super = $1; } croak "invalid superservice: $super" unless Lire::DlfSchema->has_superservice( $super ); return $SCHEMA_CACHE{$name} if $SCHEMA_CACHE{$name}; my $file = Lire::DlfSchema->_schema_file( $name ); croak "can't find XML schema definition for $name in ", join( ":", @{Lire::Config->get( 'lr_schemas_path' )} ),"\n" unless defined $file; my $file_h; open ( $file_h, "$file") or croak "can't open XML schema $file for $name schema: $!"; my $parser = new XML::Parser ( 'Handlers' => { 'Init' => \&Init, 'Final' => \&Final, 'Start' => \&Start, 'End' => \&End, 'Char' => \&Char, }, 'Namespaces' => 1, 'NoLWP' => 1, ); my $dlf_schema = eval { $parser->parse( $file_h ) }; croak "error while parsing XML definition of $name: $@" if $@; close $file_h; # Sanity checks croak "$file has '", $dlf_schema->superservice(), "' as superservice attribute when it should have '", $super, "'\n" if $dlf_schema->superservice() ne $super; croak "$file has '", $dlf_schema->id(), "' as id attribute when it should have '", $name, "'\n" if $dlf_schema->id() ne $name; return $SCHEMA_CACHE{$name} = $dlf_schema; } sub new { my ( $class, %attr ) = @_; check_param( $attr{'superservice'}, 'superservice', \&check_superservice ); check_param( $attr{'timestamp'}, 'timestamp', \&check_xml_name ); my $self = bless { 'id' => $attr{'superservice'}, 'superservice' => $attr{'superservice'}, 'timestamp_field' => $attr{'timestamp'}, 'fields_by_pos' => [], 'fields_by_name' => {}, 'title' => undef, 'description' => undef, }, $class; $self->add_field( new Lire::Field( 'name' => 'dlf_id', 'type' => 'id', 'label' => __( 'Dlf ID' ), 'description' => '' . __( <' ) ); This field contains an integer which uniquely identify this DLF record in the stream. EOD $self->add_field( new Lire::Field( 'name' => 'dlf_source', 'type' => 'string', 'label' => __( 'Dlf Source' ), 'description' => '' . __( <' ) ); This field contains an identifier relating the record to the process that created it. EOD bindtextdomain( "lire-" . $self->superservice(), ac_info( 'LR_PERL5LIB' ) . "/LocaleData" ); return $self; } sub check { my ( $self ) = @_; # Verify that the schema is valid # Check that the timestamp attribute is valid croak ( "field $self->{'timestamp_field'} doesn't exists" ) unless $self->has_field( $self->{'timestamp_field'} ); my $field = $self->timestamp_field; croak ( "field $self->{'timestamp_field'} isn't of type timestamp" ) unless $field->type() eq "timestamp"; return 1; } =pod =head2 has_superservice( $superservice ) Returns true if there is superservice named $schema_name available. An error will be thrown if the schema name isn't valid for a superservice. =cut sub has_superservice { my ($self, $superservice ) = @_; check_param( $superservice, 'superservice', sub { return ( check_xml_name($_[0]) && index($_[0], "-") == -1 ) }, 'invalid superservice schema name' ); return ( defined $SCHEMA_CACHE{$superservice} || defined $self->_schema_file( $superservice ) ); } =pod =head2 has_schema( $schema_name ) Returns true if there is $schema_name available. An error will be thrown if the schema name isn't valid. =cut sub has_schema { my ( $self, $schema_name ) = @_; check_param( $schema_name, 'schema_name', \&check_xml_name, 'invalid schema name' ); return ( defined $SCHEMA_CACHE{$schema_name} ||defined $self->_schema_file( $schema_name ) ); } sub _schema_file { my ( $self, $schema_name ) = @_; foreach my $dir ( @{Lire::Config->get( 'lr_schemas_path' )} ) { return "$dir/$schema_name.xml" if -f "$dir/$schema_name.xml"; } return undef; } =pod =head2 superservices() Returns the name of the available superservices in an array. =cut sub superservices { my $self = $_[0]; return grep { /^[^-]+$/ } $self->schemas(); } =pod =head2 schemas() Returns the name of the available schemas in an array. =cut sub schemas { my $self = $_[0]; my @schemas = keys %SCHEMA_CACHE; foreach my $dir ( @{ Lire::Config->get( 'lr_schemas_path' ) } ) { next unless -d $dir && -r $dir; opendir my $dh, $dir or croak "opendir failed on '$dir': $!"; foreach my $file ( readdir $dh ) { next unless $file =~ /^([a-zA-Z][-\w.:]+)\.xml$/; push @schemas, $1 unless grep { $_ eq $1 } @schemas; } closedir $dh; } return @schemas; } =pod =head1 SCHEMA OBJECT METHODS =head2 id() my $id = $schema->id(); This method will return the id of the schema. This will be the superservice's name for superservice's main schema. (There are other types of schemas (derived and extended schemas) for which the id will be different than the superservice's name.) =cut sub id { return $_[0]->{'id'}; } =pod =head2 superservice() my $super = $schema->superservice(); This method will return the superservice's name of the schema. =cut sub superservice { return $_[0]->{'superservice'}; } =pod =head2 title( [$new_title] ) This method will return (or change) the human readable title of the schema. (This is the content of the title element in the XML specification.) =cut sub title { my $self = $_[0]; if ( @_ == 2 ) { check_param( $_[1], 'title' ); $self->{'title'} = $_[1]; } return dgettext( "lire-$self->{'superservice'}", $self->{'title'} ); } =pod =head2 description( [$new_description] ) This method will return (or change) the description of the schema. (This is the content of the description element in the XML specification.) Be aware that this will most likely contain DocBook markup. =cut sub description { my $self = $_[0]; if ( @_ == 2 ) { $self->{'description'} = $_[1]; } return dgettext_para( "lire-$self->{'superservice'}", $self->{'description'} ); } =pod =head2 field_by_pos() my $field = $schema->field_by_pos( 0 ); This method takes an integer as parameter and return the field at that position in the schema. Fields are indexed starting at 0. This method will die() if an invalid position is passed as parameter. The method returns a Lire::Field(3pm) object. =cut sub field_by_pos { my ( $self, $pos ) = @_; croak "invalid field number: $pos" unless $pos < @{$self->{'fields_by_pos'}} && $pos >= 0; return $self->{'fields_by_pos'}[$pos]; } =pod =head2 add_field( $field ) Adds the Lire::Field $field to this schema. =cut sub add_field { my ( $self, $field ) = @_; check_object_param( $field, 'field', 'Lire::Field' ); push @{$self->{'fields_by_pos'}}, $field; $self->{'fields_by_name'}{$field->name()} = $field; $field->{'pos'} = $#{$self->{'fields_by_pos'}}; return; } =pod =head2 has_field() if ( $schema->has_field( 'test ) ) { print "schema has field 'test'\n"; } This method takes a string as parameter and returns a boolean value. That value will be true if there is a field in the schema with that name, it will be false otherwise. =cut sub has_field { my ($self, $name ) = @_; return exists $self->{'fields_by_name'}{$name}; } =pod =head2 field() my $field = $schema->field( 'from_email' ); This method takes a field's name as parameter and returns the Lire::Field(3pm) object describing that field in the schema. The method will die() if there is no field with that name in the schema. =cut sub field { my ( $self, $name ) = @_; croak "no field by that name: $name" unless $self->has_field( $name ); return $self->{'fields_by_name'}{$name}; } =pod =head2 fields() my $fields = $schema->fields(); my @fields = $schema->fields(); In array context, this method will return an array containing all the fields (as Lire::Field(3pm) objects) in the schema. The order of the fields in the array is the order of the fields in the schema. In scalar context, it will return an array reference. This method is more efficient than creating an array. DO NOT MODIFY THE RETURNED ARRAY. =cut sub fields { return wantarray ? @{$_[0]{'fields_by_pos'}} : $_[0]{'fields_by_pos'}; } =pod =head2 field_names() Returns the name of the fields in this schema. The names are in the same order than the fields. =cut sub field_names { return map { $_->name() } $_[0]->fields(); } =pod =head2 field_count() my $number_of_field = $schema->field_count; This method returns the number of fields in the schema. =cut sub field_count { return scalar @{$_[0]->{'fields_by_pos'}}; } =pod =head2 timestamp_field() my $time_field = $schema->timestamp_field; This method will return the Lire::Field(3pm) object representing the timestamp field in the schema. The timestamp field is the one that defines the sort order of the DLF records. =cut sub timestamp_field { my ($self) = @_; return $self->field( $self->{'timestamp_field'} ); } =pod =head2 is_schema_compatible() if ( $schema->is_schema_compatible( $other_schema ) ) { } This method takes a Lire::DlfSchema(3pm) object as parameter and returns a boolean value. That value will be true if the schema passed as parameter is compatible with the other, it will be false otherwise. For a superservice's schema, the only compatible schema is an object representing the same superservice's schema. =cut sub is_schema_compatible { my ( $self, $schema ) = @_; return $schema eq $self->{'id'}; } =pod =head2 can_join_schema( $schema ) Returns true if $schema can be joined with this schema. For a DlfSchema, this will be true only when $schema is an ExtendedSchema of this schema. =cut sub can_join_schema { my ( $self, $schema ) = @_; check_object_param( $schema, 'schema', 'Lire::DlfSchema' ); return ( $schema->isa( 'Lire::ExtendedSchema' ) && $schema->base() eq $self ); } sub ascii_dlf_escape_field { # Escape the value : # replace space with _ # replace 8 bit chars with ? # replace control chars with ? return $_[0] =~ tr/ \200-\377\000-\037/_?/; } # This method is part of the old style, now deprecated, DLF converter API. # It takes as parameters a list of field's names that are available in # the DLF output by the converter. (Not all services in a given # superservice will support the whole or the same subset of the # superservice's fields. Unsupported fields should contain the value # C in the output DLF.) # This method will return an anonymous subroutine that should be used by # the DLF converter to create the DLF records. The generated subroutine # takes as parameter a hash reference representing the DLF record to # create. It returns an array reference representing the DLF record's # fields. It will make sure that the field's values are in the correct # order, that the unavailable fields are marked correctly, that missing # fields are defaulted and that the field's values are escaped # appropriately. # The hash's keys should be the DLF record's field names with the value # of the field associated to the key. All the fields that are available # (as specified when the method is called) which are undefined or that # aren't present in the hash will be set in the output DLF record to the # field's default value specified in the schema. Extra keys in the hash # will be ignored. Fields that aren't supported (as specified when the # subroutine was created by the make_hashref2asciidlf_func() method) # will contain the C value. # One can write an ASCII DLF by printing the returned array reference # using a space as the join delimiter: # my $dlf = $dlf_maker->( $hash_dlf ); # print join( " ", @$dlf ), "\n"; # See the SYNOPSIS section for an example. # Beware! New DLF convertors should use the Lire::DlfConverterProcess # interface. sub make_hashref2asciidlf_func { my ( $self, @fields ) = @_; my %avail = map { $_ => 1 } @fields; my @ascii_dlf_tmpl = (); foreach my $field ( @{$self->fields}) { push @ascii_dlf_tmpl, [ $field->name, $field->default() ]; } return sub { my ($hash) = @_; my $dlf = []; foreach my $field_tmpl ( @ascii_dlf_tmpl ) { my $name = $field_tmpl->[0]; my $value; if ( $avail{$name} ) { if (defined $hash->{$name} && length $hash->{$name}) { $value = $hash->{$name}; } else { $value = $field_tmpl->[1]; # Use default } ascii_dlf_escape_field( $value ); } else { $value = "LIRE_NOTAVAIL"; } push @$dlf, $value; } return $dlf; }; } =pod =head1 SQL Related Methods These methods are used to map DLF record into SQL tables. =head2 sql_table() Returns the SQL table used to hold the DLF records of this schema. =cut sub sql_table { my ( $self, $prefix, $suffix ) = @_; $prefix = "" unless defined $prefix; $suffix = "" unless defined $suffix; return sql_quote_name( $prefix . 'dlf_' . $_[0]->{'id'} . $suffix ); } =pod =head2 create_sql_schema( $dlf_store, [ $remove ] ) This will create the SQL schemas necessary to hold the DLF records for this schema in the Lire::DlfStore. If $remove is true, a DROP TABLE will be done before creating the schema. =cut sub create_sql_schema { my ($self, $store, $remove ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); $store->_dbh()->do( "DROP TABLE " . $self->sql_table() ) if $remove; $store->_dbh()->do( $self->_create_sql_table_query() ); my $idx_sql = sprintf( "CREATE INDEX %s ON %s ( %s )", $self->sql_table( "", "_" . $self->{'timestamp_field'} . "_idx"), $self->sql_table(), $self->{'timestamp_field'} ); $store->_dbh()->do( $idx_sql ); return; } sub _create_sql_table_query { return "CREATE TABLE " . $_[0]->sql_table() . " " . $_[0]->_sql_fields_def(); } =pod =head2 needs_sql_schema_migration( $dlf_store ) This method will return true if the SQL schema isn't up-to-date in the DlfStore. The method migrate_sql_schema() can be used to bring the schema up to date. =cut sub needs_sql_schema_migration { my ( $self, $store ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); my $create_sql = $self->_create_sql_table_query(); # SQLite will remove trailing newline chomp $create_sql; my $sql = "SELECT sql FROM sqlite_master WHERE type = 'table' AND name=?"; my $sth = $store->_dbh()->prepare( $sql ); $sth->execute( $self->sql_table() ); my $table_def = $sth->fetchrow_arrayref(); $sth->finish(); return $table_def && $table_def->[0] ne $create_sql; } =pod =head2 migrate_sql_schema( $dlf_store ) Updates the SQL schemas to the current version. =cut sub migrate_sql_schema { my ( $self, $store ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); # SQLite doesn't support ALTER TABLE # Find the list of fields in common my @fields = $self->_find_fields_in_schema( $store ); # Create temporary backup my $sql = sprintf( "CREATE TEMP TABLE %s AS SELECT * FROM %s", $self->sql_table( "temp_" ), $self->sql_table() ); $store->_dbh()->do( $sql ); # Recreate the schema $self->create_sql_schema( $store, 1 ); # Migrate the data my @common_fields = (); foreach my $f ( @fields ) { push @common_fields, $f if $self->has_field( $f ); } $sql = $self->_migration_insert_query( \@common_fields ); $store->_dbh()->do( $sql ); $store->_dbh()->do( "DROP TABLE " . $self->sql_table( "temp_" ) ); return; } sub _find_fields_in_schema { my ( $self, $store ) = @_; # Since DBD::SQLite doesn't support the column_info API # we run a query to find the fields present in the schema. my $sth = $store->_dbh()->prepare( "SELECT * FROM " . $self->sql_table() . " LIMIT 1" ); $sth->execute(); my @fields = @{$sth->{'NAME'}}; $sth->finish(); return @fields; } sub _migration_insert_query { my ( $self, $common_fields ) = @_; # New fields will be set to NULL # Old fields aren't migrated my $field_list = join (", ", map { sql_quote_name( $_ ) } @$common_fields); return sprintf( "INSERT INTO %s (%s) SELECT %s FROM %s", $self->sql_table(), $field_list, $field_list, $self->sql_table( "temp_" ) ); } sub _sql_fields { return $_[0]->fields(); } sub _sql_fields_def { my $self = $_[0]; my @defs = (); foreach my $f ( $self->_sql_fields() ) { push @defs, " " . sql_quote_name( $f->name() ) . " " . $f->sql_type(); } return "(\n" . join( ",\n", @defs ) . "\n)\n"; } =pod =head2 dlf_query( $sort_spec ) Returns a Lire::DlfQuery object which can be use to return all DLF records sorted according to $sort_spec. Sort spec is a white-space delimited list of sort field names. They must be present in the current schema. If the field's name is prefixed by '-', descending sort order will be used. =cut sub dlf_query { my ( $self, $sort_spec ) = @_; my $query = new Lire::DlfQuery( $self->{'id'} ); foreach my $f ( $self->fields() ) { $query->add_field( $f->name() ); } $query->set_sort_spec( $sort_spec ) if $sort_spec; return $query; } =pod =head2 insert_sql_query() Returns the INSERT SQL statement that should be used to insert DLF records in the stream. A DBI::st handle prepared with that query needs to be passed as parameter to execute_insert_query(). =cut sub sql_insert_query { my $self = $_[0]; my @fields = map { $_->name() } $self->_sql_fields(); return "INSERT INTO " . $self->sql_table() . " (" . join( ", ", map { sql_quote_name( $_ ) } @fields ) . ") VALUES (" . join( ",", ("?") x scalar @fields ) . ")"; } =pod =head2 sql_clean_query( $with_time ) Returns the DELETE statement that can be use to delete the DLF records in this schema. If $with_time is true, the query can be use for selective cleaning. One bind timestamp parameter should be passed when the query is executed and all records which are older than this timestamp will be deleted. =cut sub sql_clean_query { my ($self, $with_time) = @_; my $table = $self->sql_table(); if ( $with_time ) { my $ts_field = sql_quote_name( $self->{'timestamp_field'} ); return qq{DELETE FROM $table WHERE $ts_field < ?}; } else { return "DELETE FROM $table"; } } =pod =head2 sql_clean_period_query() Returns the DELETE statement that can be use to delete the DLF records in this schema. The query should be passed two bind parameters. These parameters will be the time boundaries between which records should be deleted from the schema. =cut sub sql_clean_period_query { my $self = $_[0]; my $table = $self->sql_table(); my $ts_field = sql_quote_name( $self->{'timestamp_field'} ); return qq{DELETE FROM $table WHERE $ts_field >= ? AND $ts_field < ?}; } use vars qw( $LDSML_NS %LDSML_ELEMENTS ); BEGIN { %LDSML_ELEMENTS = map { $_ => 1 } qw( dlf-schema derived-schema extended-schema field title description ); $LDSML_NS = "http://www.logreport.org/LDSML/"; } sub Init { my ($expat) = @_; $expat->{'lire_curr_schema'} = undef; $expat->{'lire_curr_field'} = undef; $expat->{'lire_curr_desc'} = undef; return; } sub Final { my ( $expat ) = @_; return $expat->{'lire_curr_schema'}; } sub Start { my ( $expat, $name ) = @_; my $ns = $expat->namespace($name); $ns ||= ""; # Remove warnings if ( $ns eq $LDSML_NS ) { # This is one of our element error( $expat, "unknown element: $name" ) unless exists $LDSML_ELEMENTS{$name}; { no strict 'refs'; my $sub = $name . "_start"; $sub =~ s/-/_/g; # Hyphen aren't allowed in element name $sub->( @_ ); }; } else { # If we are in lire:description, this is probably a # DocBook element, append it to the current description. my $lire_desc = $expat->generate_ns_name( "description", $LDSML_NS ); if ( $expat->within_element( $lire_desc ) ) { $expat->{'lire_curr_desc'} .= $expat->original_string(); } else { error( $expat, "unknown element: $name" ); } } return; } sub End { my ( $expat, $name ) = @_; my $ns = $expat->namespace($name); $ns ||= ""; # Remove warnings if ( $ns eq $LDSML_NS ) { # This is one of our element error( $expat, "unknown element: $name" ) unless exists $LDSML_ELEMENTS{$name}; { no strict 'refs'; my $sub = $name . "_end"; $sub =~ s/-/_/g; # Hyphen aren't allowed in element name $sub->( @_ ); } } else { # If we are in lire:description, this is probably a # DocBook element, append it to the current description. my $lire_desc = $expat->generate_ns_name( "description", $LDSML_NS ); if ( $expat->within_element( $lire_desc ) ) { $expat->{'lire_curr_desc'} .= $expat->original_string(); } else { error( $expat, "unknown element: $name" ); } } return; } sub Char { my ( $expat, $str ) = @_; # Character should only appear in title and description my $lire_title = $expat->generate_ns_name( "title", $LDSML_NS ); my $lire_desc = $expat->generate_ns_name( "description", $LDSML_NS ); if ( $expat->in_element( $lire_title )) { $expat->{'lire_curr_title'} .= $str; } elsif ( $expat->within_element( $lire_desc )) { # Use original_string because we don't want parsed entities. $expat->{'lire_curr_desc'} .= $expat->original_string(); } return; } sub dlf_schema_start { my ( $expat, $name, %attr ) = @_; eval { $expat->{'lire_curr_schema'} = new Lire::DlfSchema( %attr ); }; error( $expat, $@ ) if $@; return; } sub dlf_schema_end { my ( $expat, $name ) = @_; eval { $expat->{'lire_curr_schema'}->check(); }; error( $expat, $@ ) if $@; return; } sub derived_schema_start { my ( $expat, $name, %attr ) = @_; eval { $expat->{'lire_curr_schema'} = new Lire::DerivedSchema( %attr ); }; error( $expat, $@ ) if $@; return; } sub derived_schema_end { my ( $expat, $name ) = @_; eval { $expat->{'lire_curr_schema'}->check(); }; error( $expat, $@ ) if $@; return; } sub extended_schema_start { my ( $expat, $name, %attr ) = @_; eval { $expat->{'lire_curr_schema'} = new Lire::ExtendedSchema( %attr ); }; error( $expat, $@ ) if $@; return; } sub extended_schema_end { my ( $expat, $name ) = @_; eval { $expat->{'lire_curr_schema'}->check(); }; error( $expat, $@ ) if $@; return; } sub error { my ( $expat, $msg ) = @_; my $line = $expat->current_line(); croak $msg, " at line ", $line, "\n"; return; } sub field_start { my ( $expat, $name, %attr ) = @_; check_param( $attr{'name'}, 'name', \&check_xml_name, 'invalid field name' ); check_param( $attr{'type'}, 'type', \&check_type, 'invalid value for type attribute' ); $expat->{'lire_curr_field'} = new Lire::Field( 'name' => $attr{'name'}, 'i18n_domain' => 'lire-'. $expat->{'lire_curr_schema'}->superservice(), 'type' => $attr{'type'}, 'label' => $attr{'label'}, ); return; } sub field_end { my ( $expat, $name ) = @_; $expat->{'lire_curr_schema'}->add_field( $expat->{'lire_curr_field'} ); delete $expat->{'lire_curr_field'}; return; } sub title_start { my ( $expat, $name ) = @_; $expat->{'lire_curr_title'} = ""; return; } sub in_schema_element { my ( $expat ) = @_; my $lire_dlf_schema = $expat->generate_ns_name( "dlf-schema", $LDSML_NS ); my $lire_ext_schema = $expat->generate_ns_name( "extended-schema", $LDSML_NS ); my $lire_der_schema = $expat->generate_ns_name( "derived-schema", $LDSML_NS ); return $expat->in_element( $lire_dlf_schema ) || $expat->in_element( $lire_ext_schema ) || $expat->in_element( $lire_der_schema ); } sub title_end { my ( $expat, $name ) = @_; my $lire_field = $expat->generate_ns_name( "field", $LDSML_NS ); if ( $expat->in_element( $lire_field)) { $expat->{'lire_curr_field'}{'title'} = $expat->{'lire_curr_title'}; } elsif ( in_schema_element( $expat ) ) { $expat->{'lire_curr_schema'}{'title'} = $expat->{'lire_curr_title'}; } else { error( $expat, "encountered unexpected title" ); } return; } sub description_start { my ( $expat, $name ) = @_; $expat->{'lire_curr_desc'} = ""; return; } sub description_end { my ( $expat, $name ) = @_; my $lire_field = $expat->generate_ns_name( "field", $LDSML_NS ); if ( $expat->in_element( $lire_field)) { $expat->{'lire_curr_field'}{'description'} = $expat->{'lire_curr_desc'}; } elsif ( in_schema_element( $expat )) { $expat->{'lire_curr_schema'}{'description'} = $expat->{'lire_curr_desc'}; } else { error( $expat, "encountered unexpected description" ); } return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Field(3pm), Lire::ExtendedSchema(3pm), Lire::DlfConverter(3pm), Lire::DerivedSchema(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: DlfSchema.pm,v 1.58 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001, 2002, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/First.pm0000644000175000017500000001533210765035043013234 00000000000000package Lire::First; use strict; use base qw/ Lire::SimpleStat /; use Carp; use Lire::Utils qw/ sql_quote_name check_object_param /; use Lire::DataTypes qw/ is_numeric_type /; =pod =head1 NAME Lire::First - Lire class that implements the first operator =head1 SYNOPSIS use Lire::First =head1 DESCRIPTION Class that implements the first operator. This operator will output the first value appearing in its field when the DLF records are sorted according to the C attribute. The default sort order is the default timestamp sort. =head1 METHODS =head2 new( %params ) Creates a new Lire::First object. The field attribute can be specified in the C parameter and the sort order can be passed in the C parameter. =cut sub new { my ( $class, %params ) = @_; my $self = bless {}, $class; $self->init( %params, 'op' => 'first' ); $self->sort_fields( $params{'sort_fields'} ); return $self; } #------------------------------------------------------------------------ # Method field( [$field] # # Overrides Lire::SimpleStat one since the field doesn't have # to be numeric. sub field { my ($self, $field ) = @_; if ( @_ == 2 ) { if ( defined $field ) { croak "'$field' isn't a defined field in the specification's schemas" unless $self->report_spec()->has_field( $field ); } $self->{'field'} = $field; } $self->{'field'}; } =pod =head2 sort_fields( [$new_sort_fields] ) Returns the fields that are going to be used to sort the DLF records. This a reference to an array of DLF field names. If the $new_sort_fields parameter is set, it will be used as the new sort order. It must be an array reference and should only contains valid field names for the current report specification's schema. When no sort_fields are set, the default is to use the default timestamp field. =cut sub sort_fields { my ( $self, $sort_fields ) = @_; if ( @_ == 2 ) { if ( defined $sort_fields ) { check_object_param( $sort_fields, 'sort_fields', 'ARRAY' ); foreach my $f ( @$sort_fields ) { croak "'$f' isn't a defined field in the specification's schema" unless $self->report_spec()->has_field( $f ); } } $self->{'sort_fields'} = $sort_fields; } return $self->{'sort_fields'}; } #------------------------------------------------------------------------ # Method xml_attrs() # # Implementation needed by Lire::Aggregate sub xml_attrs { my ($self) = @_; my $attr = $self->SUPER::xml_attrs; if ( exists $self->{'sort_fields'} ) { my $sort_fields = join " ", @{$self->{'sort_fields'}}; $attr .= qq{ sort="$sort_fields"}; } return $attr; } # Overrides Lire::SimpleStat::sql_required_fields sub sql_required_fields { my $self = $_[0]; my @fields = ( $self->{'field'} ); push @fields, @{ $self->{'sort_fields'} } if defined $self->{'sort_fields'}; return \@fields; } # Overrides Lire::Aggregate::build_query sub build_query { my ( $self, $query ) = @_; $self->_build_first_query( $query ); $self->set_missing_cases_aggr_expr( $query ); } sub _build_first_query { my ( $self, $query ) = @_; my @fields = map { sql_quote_name( $_ ) } @{ $self->sql_required_fields()}; $query->add_aggr_field( $self->name(), sprintf( 'lr_first(%s)', join( ",", @fields ))); if ( $self->{'sort_fields'} ) { $query->add_aggr_field( $self->name() . '_key', sprintf( 'lr_first_key(%s)', join( ",", @fields ))); } return; } # Overrides Lire::SimpleStat::create_value sub create_value { my ( $self, $parent_group, $row ) = @_; my $v = $self->SUPER::create_value( $parent_group, $row ); if ( ! is_numeric_type( $self->dlf_field()->type() ) ) { $v->{'content'} = $row->{ $self->name() }; } $v->{'total'} = $row->{ $self->name() . "_key" }; return $v; } # Implements Lire::ReportOperator::init_merge() sub init_merge { my $self = $_[0]; $self->SUPER::init_merge(); my $sort_fields = $self->sort_fields; unless ( $sort_fields && @$sort_fields ) { $sort_fields = [ $self->report_spec()->schema()->timestamp_field()->name() ]; } my @cmp = (); my $i = 0; foreach my $f ( @$sort_fields ) { my $type = $self->report_spec()->schema()->field( $f )->type(); my $cmp = is_numeric_type( $type ) ? '<=>' : 'cmp'; push @cmp, "\$_[0][$i] $cmp \$_[1][$i]"; $i++; } my $sort_code = "sub { " . join( " && ", @cmp ) . " }"; $self->{'sort_func'} = eval $sort_code; croak "failed to compile sort function ($sort_code): $@" if $@; $self->{'total_func'} = sub { return defined $_[0] ? join( " ", @{$_[0]} ) : ''; }; return; } # Implements Lire::ReportOperator::init_group_data() sub init_group_data { return []; } # Implements Lire::ReportOperator::merge_group_data() sub merge_group_data { my ( $self, $value, $data ) = @_; return unless $value->{'total'}; my $fields = [ split / /, $value->{'total'} ]; unless (defined $data->[0]) { $data->[0] = $value->{'value'}; $data->[1] = $fields; return; } # Change the value only if the fields sorts before the last one if ( $self->{'sort_func'}->( $fields, $data->[1] ) < 0 ) { $data->[0] = $value->{'value'}; $data->[1] = $fields; } return; } # Implements Lire::Aggregate::data2dlf() sub data2dlf { my ($self, $data) = @_; my $name = $self->name(); return { "$name" => $data->[0], "${name}_key" => $self->{'total_func'}->( $data->[1] ), "_lr_${name}_mc" => $self->missing_cases( $data ), }; } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::ReportOperator(3pm), Lire::Aggregator(3pm), Lire::Aggregate(3pm), Lire::Last(3pm) =head1 AUTHORS Francis J. Lacoste Wolfang Sourdeau =head1 VERSION $Id: First.pm,v 1.15 2008/03/09 19:27:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Min.pm0000644000175000017500000000452610765035043012673 00000000000000package Lire::Min; use strict; use base qw/ Lire::SimpleStat /; use Carp; use Lire::Utils qw/ sql_quote_name /; =pod =head1 NAME Lire::Min - Lire class that implements the min operator =head1 SYNOPSIS use Lire::Min =head1 DESCRIPTION Class that implements the min operator. This operator will find the minimum value appearing in a DLF field among a group of DLF records. =head1 METHODS =head2 new( %params ) Creates a new Lire::Min object. =cut sub new { my $self = bless {}, shift; $self->init( @_, 'op' => 'min' ); return $self; } # Implements Lire::Aggregate::sql_aggr_expr sub sql_aggr_expr { my $self = $_[0]; return 'min(' . sql_quote_name( $self->{'field'} ) . ')'; } # Implements Lire::ReportOperator::init_group_data sub init_group_data { my $scalar = undef; return \$scalar; } # Implements Lire::ReportOperator::merge_group_data sub merge_group_data { my ( $self, $value, $data ) = @_; return if lc $value->{'value'} eq 'nan'; $$data = $value->{'value'} unless ( defined $$data ); # To merge two mins, we keep the lowest $$data = $value->{'value'} if $value->{'value'} < $$data; return; } # Implements Lire::ReportOperator::end_group_data sub end_group_data { my ( $self, $data ) = @_; $$data = "NaN" unless defined $$data; return; } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::ReportOperator(3pm), Lire::Aggregator(3pm), Lire::Aggregate(3pm). =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: Min.pm,v 1.9 2008/03/09 19:27:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001, 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Aggregate.pm0000644000175000017500000002155110460673253014036 00000000000000package Lire::Aggregate; use strict; use base qw/ Lire::ReportOperator /; use Carp; use Lire::DataTypes qw/ check_field /; use Lire::ReportOperator; use Lire::Utils qw/ sql_quote_name check_param /; =pod =head1 NAME Lire::Aggregate - Base class for all operators that compute values from a group of DLF records =head1 SYNOPSIS use Lire::Aggregate; use base qw/ Lire::Aggregate /; =head1 DESCRIPTION The Lire::Aggregate is the base class of all operators that computes values from a group of DLF records. These are the operators that are used inside aggregators. This package also defines most of the classes that represents the group operators available in Lire report specification. =head1 METHODS FOR SUBCLASSES OF Aggregate =head2 init( %params ) Two supplemental parameters are needed for Aggregates: =over =item parent The Lire::Aggregator which contain this Aggregate. =item name The identifier that can be used to find this operator in the report specification. It will be returned by the name() method. =back =cut sub init { my ( $self, %params ) = @_; check_param( $params{'parent'}, 'parent' ); check_param( $params{'name'}, 'name' ); $self->SUPER::init( %params ); $self->set_name( $params{'name'} ); return; } =pod =head2 print( $fh, $prefix) This methods implements the print() method required by Lire::ReportOperator. It prints an empty XML element named after op(). It also takes care of writing the name and label attributes. Other attributes can be added to the XML element by overriding the xml_attrs() method. =cut sub print { my ($self,$fh, $prefix) = @_; $fh ||= \*STDOUT; $prefix ||= 0; my $pfx = " " x $prefix; my $attrs = $self->xml_attrs; print $fh $pfx, "op, ' name="', $self->name, '"'; print $fh qq{ label="$self->{'label'}"} if $self->{'label'}; print $fh $attrs if length $attrs; print $fh "/>\n"; } =pod =head2 xml_attrs() This method can be used to write additional XML attributes. The returned string will be output in the XML element. =cut sub xml_attrs { return ""; } # Implemented Lire::ReportOperator::name sub name { return $_[0]{'name'}; } =pod =head2 set_name( $name ) Changes this operator's name. =cut sub set_name { my ( $self, $name ) = @_; check_param( $name, 'name', \&check_field, 'invalid field name' ); croak "name '$name' is already defined" if defined $self->{'name'} && $name ne $self->{'name'} && $self->last_parent->is_name_defined( $name ); $self->{'name'} = $name; return; } =pod =head2 create_numerical_info( $group_info ) Subclass must implement this method. The $group_info parameter is a Lire::Report::GroupInfo object to which the operator implementation should add the appropriate ColumnInfo object to represent the data generated by the aggregate. =cut sub create_numerical_info { croak( "unimplemented create_numerical_info() method in ", ref $_[0] ); } =pod =head2 build_query( $query ) FIXME. Provides a default implementation of build_query =cut sub build_query { my ( $self, $query ) = @_; $query->add_aggr_field( $self->name(), $self->sql_aggr_expr() ); $self->set_missing_cases_aggr_expr( $query ); return; } =pod =head2 set_missing_cases_aggr_expr( $query ) Adds the aggregate expression to compute the number of missing cases based on the required fields returned by the sql_required_fields() method. The method set_missing_cases_value() can be used to set the value from the returned DLF row. =cut sub set_missing_cases_aggr_expr { my ( $self, $query ) = @_; my $req_fields_expr = join( ",", map { sql_quote_name( $_ ) } @{$self->sql_required_fields} ); $query->add_aggr_field( '_lr_' . $self->name() . '_mc', sprintf( 'lr_missing_cases(%s)', $req_fields_expr ) ); return; } =pod =head2 set_missing_cases_value( $row, $value ) Sets the missing-cases value in $value to the value computed by the expression sets using set_missing_cases_aggr_expr(). =cut sub set_missing_cases_value { my ( $self, $row, $value ) = @_; $value->{'missing_cases'} = $row->{'_lr_' . $self->name() . '_mc'}; return; } =pod =head2 sql_aggr_expr() Method used by the default implementation of build_query(). It should return the SQL agregate expression that should be associated to this Aggregate's name. For example, a simple Count implementation could have returned 'count(*)' here. =cut sub sql_aggr_expr { croak( "unimplemented sql_aggr_expr() method in ", ref $_[0] ); } =pod =head2 sql_required_fields() Method used by the set_missing_cases_aggr_expr() to sets an aggregate expression that will return the number of missing cases for this aggregate. It should returns a list of fields that will create a missing case when a value is NULL. =cut sub sql_required_fields { croak( "unimplemented sql_required_fields() method in ", ref $_[0] ); } =pod =head2 create_value( $parent_group, $row ) Method that is used by Aggregator when building the report table. The report should return an hash reference with the appropriate keys set. Consult Lire::Report::Entry(3pm) for details. The $parent_group parameter is the Lire::Report::Group to which the value is added. This will be the table or containing group for values added to Entries, and it will be the Group's parent when creating a summary value. The $row parameter is an hash ref containing the DlfResult row for which the value should be created. Implementation should use the set_missing_cases_value() method to set the value's 'missing_cases' attribute. =cut sub create_value { croak( "unimplemented create_value() method in ", ref $_[0] ); } # Defines Lire::ReportOperator::init_merge() sub init_merge {} # Defines Lire::ReportOperator::end_merge() sub end_merge {} # OPTIMIZATION OF THE DATA STRUCTURE #. # Scalar ref takes less place then array refs which takes less spec # then hash ref. We use only scalar or array refs. # # As a side effects, we also get a little speed optimization : # perl -MBenchmark=cmpthese -e ' # my $dummy = 0; # my $scalar = \$dummy; # my $array = [0]; # my $hash = { 'value' => 0}; # cmpthese( 500000, { # 'SCALAR' => sub { $$scalar++ }, # 'ARRAY' => sub { $array->[0]++ }, # 'HASH' => sub { $hash->{'value'}++ }, # }); # Benchmark: timing 500000 iterations of ARRAY, HASH, SCALAR... # ARRAY: 0 wallclock secs ( 0.57 usr + 0.00 sys = 0.57 CPU) @ 877192.98/s (n=500000) # HASH: 1 wallclock secs ( 0.67 usr + 0.00 sys = 0.67 CPU) @ 746268.66/s (n=500000) # SCALAR: 1 wallclock secs ( 0.41 usr + 0.00 sys = 0.41 CPU) @ 1219512.20/s (n=500000) # Rate HASH ARRAY SCALAR # HASH 746269/s -- -15% -39% # ARRAY 877193/s 18% -- -28% # SCALAR 1219512/s 63% 39% -- # # Make default implementation uses a scalar reference # Implements Lire::ReportOperator::init_group_data sub init_group_data { my $scalar = 0; return \$scalar; } # Implements Lire::ReportOperator::end_group_data sub end_group_data {} # Implements Lire::ReportOperator::add_entry_value sub add_entry_value { my ( $self, $entry, $data ) = @_; my $v = $self->create_value( $entry->group(), $self->data2dlf( $data ) ); $entry->add_value( %$v ); return; } # Method used by Lire::Aggregator:: to dispath to # Lire::*::create_value() sub data2dlf { croak "Unimplemented data2dlf() in ", ref $_[0]; } #------------------------------------------------------------------------ # missing_cases( $data ) # # This method returns the number of missing-cases encountered # while processing $data. sub missing_cases { my ( $self, $data ); return 0 unless ( defined $self->{'_missing_cases'} && defined $self->{'_missing_cases'}{$data} ); return $self->{'_missing_cases'}{$data}; } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::ReportOperator(3pm), Lire::Aggregator(3pm). =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 VERSION $Id: Aggregate.pm,v 1.16 2006/07/23 13:16:27 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/DlfAnalyserProcess.pm0000644000175000017500000002041710460673254015714 00000000000000package Lire::DlfAnalyserProcess; use strict; use Lire::PluginManager; use Lire::DlfQuery; use Lire::DlfSchema; use Lire::FilterSpec; use Lire::FilterExpr; use Lire::Utils qw/ check_param check_object_param period_range /; use POSIX qw/ strftime /; use Carp; =pod =head1 NAME Lire::DlfAnalyseProcess - Object that controls the analysis process. =head1 SYNOPSIS use Lire::DlfStore; use Lire::DlfAnalyserProcess; my $store = Lire::DlfStore->open( "store" ); my $process = new Lire::DlfAnalyserProcess( $store, $analyser_name, $analyser_config, $dlf_source ); $process->run_analysis_job(); print "DLF records created: ", $process->dlf_count(), "\n"; print "Errors encountered: ", $process->errors_count(), "\n"; =head1 DESCRIPTION This object encapsulates the Lire DLF analysis process. It takes as a Lire::DlfStore, the name of the analyser, its configuration and optionally, a dlf_source ID. When a dlf_source is used, the analysis will only be done using the DLF coming from that source. The object provides the API to the converter. Methods are also available to query information on the conversion process. =head1 new( $store, $analyser_name, $analyser_config, [ $dlf_source ] ); Create a Lire::DlfAnalysisProcess. =cut sub new { my ( $class, $store, $analyser, $config, $dlf_source ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); check_param( $analyser, 'analyser_name' ); check_param( $config, 'analyser_config' ); croak "no analyser '$analyser' was registered" unless Lire::PluginManager->has_plugin( 'dlf_analyser', $analyser ); return bless { '_store' => $store, '_dlf_source' => $dlf_source, '_analyser' => $analyser, '_analyser_config' => $config, }, $class; } =pod =head2 run_analysis_job() Import the log data from ImportJob as DLF. This method will throw an exception if it is called more than once. =cut sub run_analysis_job { my ( $self, $time ) = @_; $time ||= time; $self->_init_process( $time ); my $analyser = Lire::PluginManager->get_plugin( 'dlf_analyser', $self->{'_analyser'} ); eval { $analyser->analyse( $self, $self->{'_analyser_config'} ); }; $self->error( $@ ) if $@; $self->_save_analysis_stats(); $self->{'_log_stream'}->close(); delete $self->{'_log_stream'}; $self->{'_dlf_stream'}->close(); delete $self->{'_dlf_stream'}; return; } sub _init_process { my ($self, $time ) = @_; my $analyser = Lire::PluginManager->get_plugin( 'dlf_analyser', $self->{'_analyser'} ); $self->{'_time'} = $time; $self->{'_dlf_count'} = 0; $self->{'_error_count'} = 0; $self->{'_job_id'} = strftime( "$self->{'_analyser'}-%Y%m%d_%H%M%S", localtime( $time ) ); $self->{'_dlf_stream'} = $self->{'_store'}->open_dlf_stream( $analyser->dst_schema(), 'w' ); $self->{'_log_stream'} = $self->{'_store'}->open_dlf_stream( 'lire_import_log', 'w' ); return; } sub _save_analysis_stats { my $self = $_[0]; my $stream = $self->{'_store'}->open_dlf_stream( 'lire_import_stats', 'w'); $stream->write_dlf( { 'time_start' => $self->{'_time'}, 'elapsed' => time() - $self->{'_time'}, 'error_count' => $self->{'_error_count'}, 'dlf_count' => $self->{'_dlf_count'}, 'job_name' => $self->{'_analyser'}, 'job_id' => $self->{'_job_id'}, } ); $stream->close(); return; } =pod =head2 job_id() Returns the job identifier associated to this process. =cut sub job_id { return $_[0]{'_job_id'}; } =pod =head2 dlf_store() Returns the Lire::DlfStore in which this conversion process is storing the DLF records. =cut sub dlf_store { return $_[0]{'_store'}; } =pod =head2 dlf_source() Returns the source from which the DLF should come in the src_schema to be analysed. =cut sub dlf_source { return $_[0]{'_dlf_source'}; } =pod =head2 dlf_analyser() Returns the name of the analyser which will be run. =cut sub dlf_analyser { return $_[0]{'_analyser'}; } =pod =head2 dlf_analyser_config() Returns the analysis configuration data that should be used by the converter. =cut sub dlf_analyser_config { return $_[0]{'_analyser_config'}; } =pod =head2 dlf_count() Returns the number of DLF records created. =cut sub dlf_count { return $_[0]{'_dlf_count'}; } =pod =head2 error_count() Returns the number of errors encountered in the conversion process. =cut sub error_count { $_[0]{'_error_count'} } =pod =head2 source_filter() Returns a Lire::FilterExpr which should be used to limit the DLF records to analyse. This method returns null if the whole DLF stream should be analysed. =cut sub source_filter { my $self = $_[0]; return undef unless defined $self->{'_dlf_source'}; my $plugin = Lire::PluginManager->get_plugin( 'dlf_analyser', $self->{'_analyser'} ); my $schema = Lire::DlfSchema::load_schema( $plugin->src_schema() ); my $spec = new Lire::FilterSpec(); $spec->superservice( $schema->superservice() ); $spec->schema( $schema->id() ) if $schema->id() ne $schema->superservice(); return new Lire::FilterExpr::DlfSource( 'container' => $spec, 'value' => $self->{'_dlf_source'} ); } =pod =head1 API FOR THE DLF ANALYSERS This is the object that encapsulates the DLF implementation and hides the complexitity of the storage framework from the DLF analysers. It offers the following methods to the DLf converter. =head2 write_dlf( $dlf, [$related_to] ) This writes the $dlf DLF record conforming the $schema's schema in the Lire::DlfStore. $Dlf is an hash reference. Keys are the schema's field name. Undefined value means that this field isn't available in that record. When writing to a derived schema, the $related_to parameter can be an arrayr reference containing the dlf_ids of the related record. =cut sub write_dlf { my ( $self, $dlf, $dlf_ids ) = @_; check_object_param( $dlf, 'dlf', 'HASH' ); check_object_param( $dlf_ids, 'related_to', 'ARRAY' ) if defined $dlf_ids; $dlf->{'dlf_source'} = $self->{'_job_id'}; $self->{'_dlf_stream'}->write_dlf( $dlf, $dlf_ids ); $self->{'_dlf_count'}++; return; } =pod =head2 error( $error_msg ); Method that should be used by the Lire::Analyser to report that an error was encountered during the analysis process. $error_msg should be used to report the nature of the error. =cut sub error { my ( $self, $error_msg ) = @_; check_param( $error_msg, 'error_msg' ); $self->{'_log_stream'}->write_dlf( { 'time' => time(), 'job_name' => $self->{'_analyser'}, 'job_id' => $self->{'_job_id'}, 'type' => 'error', 'msg' => $error_msg, } ); $self->{'_error_count'}++; return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfStore(3pm) Lire::DlfAnalyser(3pm) =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: DlfAnalyserProcess.pm,v 1.10 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/SQLExt/0000755000175000017500000000000011677607767013030 500000000000000lire-2.1.1/all/lib/Lire/SQLExt/LrTimeslot.pm0000644000175000017500000000351310460672576015373 00000000000000package Lire::SQLExt::LrTimeslot; use strict; use Lire::WeekCalculator; use vars qw/ $calc /; my %unit_index = ( 'h' => 2, 'd' => 6, 'M' => 4, 'm' => 1, 's' => 0 ); sub lr_timeslot { my ( $t, $mult, $unit ) = @_; return undef unless ( defined $t && defined $mult && defined $unit ); my $idx = $unit_index{$unit}; return undef unless defined $idx; my $x = ( localtime ( $t ) )[$idx]; return $x - ( $x % $mult ); } sub lr_timeslot_week { my ( $t, $mult ) = @_; return undef unless ( defined $t && defined $mult ); $calc ||= new Lire::WeekCalculator(); return int( ($calc->week_number( $t ) - 1) / $mult ) * $mult + 1; } 1; __END__ =pod =head1 NAME Lire::SQLExt::LrTimeslot - FILL ME IN =head1 SYNOPSIS FILL ME IN =head1 DESCRIPTION FILL ME IN =head1 SEE ALSO Lire::DlfConverter(3pm) =head1 VERSION Id: LrTimeslot.pm,v 1.3 2003/10/14 12:59:55 wsourdeau Exp $ =head1 AUTHOR Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/SQLExt/Registry.pm0000644000175000017500000000571210460673257015105 00000000000000package Lire::SQLExt::Registry; use strict; use vars qw/@EXT_FUNCTIONS @EXT_AGGREGATES/; use Lire::SQLExt::LrMissingCases; use Lire::SQLExt::LrFirst; use Lire::SQLExt::LrLast; use Lire::SQLExt::LrCountUniq; use Lire::SQLExt::LrMatch; use Lire::SQLExt::LrRangegroup; use Lire::SQLExt::LrTimegroup; use Lire::SQLExt::LrTimeslot; @EXT_FUNCTIONS = ( [ 'lr_match', 3, \&Lire::SQLExt::LrMatch::lr_match ], [ 'lr_timegroup_sec', 2, \&Lire::SQLExt::LrTimegroup::lr_timegroup_sec ], [ 'lr_timegroup_day', 1, \&Lire::SQLExt::LrTimegroup::lr_timegroup_day ], [ 'lr_timegroup_week', 2, \&Lire::SQLExt::LrTimegroup::lr_timegroup_week ], [ 'lr_timegroup_month', 2, \&Lire::SQLExt::LrTimegroup::lr_timegroup_month], [ 'lr_timegroup_year', 2, \&Lire::SQLExt::LrTimegroup::lr_timegroup_year ], [ 'lr_timeslot', 3, \&Lire::SQLExt::LrTimeslot::lr_timeslot], [ 'lr_timeslot_week', 2, \&Lire::SQLExt::LrTimeslot::lr_timeslot_week ], [ 'lr_rangegroup', 5, \&Lire::SQLExt::LrRangegroup::lr_rangegroup], [ 'lr_rangegroup_geo', 6, \&Lire::SQLExt::LrRangegroup::lr_rangegroup_geo ], ); @EXT_AGGREGATES = ( [ 'lr_missing_cases', -1, 'Lire::SQLExt::LrMissingCases' ], [ 'lr_first', -1, new Lire::SQLExt::LrFirst() ], [ 'lr_first_key', -1, new Lire::SQLExt::LrFirst( 'key' ) ], [ 'lr_last', -1, new Lire::SQLExt::LrLast( ) ], [ 'lr_last_key', -1, new Lire::SQLExt::LrLast( 'key') ], [ 'lr_count_uniq', -1, 'Lire::SQLExt::LrCountUniq' ], ); sub register_functions { my ( $self, $dbh ) = @_; foreach my $func_desc ( @EXT_FUNCTIONS ) { $dbh->func( $func_desc->[0], $func_desc->[1], $func_desc->[2], "create_function" ); } return; } sub register_aggregates { my ( $self, $dbh ) = @_; foreach my $aggr_desc ( @EXT_AGGREGATES ) { $dbh->func( $aggr_desc->[0], $aggr_desc->[1], $aggr_desc->[2], "create_aggregate" ); } return; } 1; __END__ =pod =head1 NAME Lire::SQLExt::Registry - FILL ME IN =head1 SYNOPSIS FILL ME IN =head1 DESCRIPTION FILL ME IN =head1 SEE ALSO Lire::DlfConverter(3pm) =head1 VERSION $Id: Registry.pm,v 1.9 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/SQLExt/LrCountUniq.pm0000644000175000017500000000276310460673257015523 00000000000000package Lire::SQLExt::LrCountUniq; use strict; use Digest::MD5 qw/ md5 / ; sub new { return bless { '_keys' => {} }, shift; } sub step { my ( $self, @params ) = @_; return if grep { ! defined $_ } @params; my $key = join( '\0', @params ); $self->{'_keys'}->{md5( $key )} = 1; return; } sub finalize { my $self = $_[0]; my $count = keys %{$self->{'_keys'}}; $self->{'_keys'} = {}; return $count; } 1; __END__ =pod =head1 NAME Lire::SQLExt::LrCountUniq - FILL ME IN =head1 SYNOPSIS FILL ME IN =head1 DESCRIPTION FILL ME IN =head1 SEE ALSO Lire::DlfConverter(3pm) =head1 VERSION $Id: LrCountUniq.pm,v 1.3 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/SQLExt/LrTimegroup.pm0000644000175000017500000000477210460673257015553 00000000000000package Lire::SQLExt::LrTimegroup; use strict; use Time::Timezone; use Time::Local; use Lire::WeekCalculator; use vars qw/ $calc /; sub lr_timegroup_sec { my ( $t, $period_size ) = @_; return undef unless ( defined $t && defined $period_size ); return int($t) - ( $t % $period_size ); } sub lr_timegroup_day { my $t = $_[0]; return undef unless defined $t; return int($t) - ( $t % 86400 ) - tz_local_offset( $t ); } sub lr_timegroup_week { my ( $t, $mult ) = @_; return undef unless ( defined $t && defined $mult ); $calc ||= new Lire::WeekCalculator(); my ($month, $year) = (localtime $t )[4,5]; my $week_no = $calc->week_number( $t ); $year++ if ( $month > 1 && $week_no == 1 ); $week_no = int( ($week_no - 1) / $mult ) * $mult + 1 if $mult > 1; return $calc->week_start( $year, $week_no ); } sub lr_timegroup_month { my ( $t, $mult ) = @_; return undef unless ( defined $t && defined $mult ); my ( $month, $year ) = ( localtime $t )[4,5]; $month = int( $month / $mult ) * $mult if $mult > 1; return timelocal( 0, 0, 0, 1, $month, $year ); } sub lr_timegroup_year { my ( $t, $mult ) = @_; return undef unless ( defined $t && defined $mult ); my $year = (localtime $t)[5] + 1900; $year = int( ( $year - 1 ) / $mult ) * $mult + 1 if $mult > 1; return timelocal( 0, 0, 0, 1, 0, $year - 1900 ); } 1; __END__ =pod =head1 NAME Lire::SQLExt::LrTimegroup - FILL ME IN =head1 SYNOPSIS FILL ME IN =head1 DESCRIPTION FILL ME IN =head1 SEE ALSO Lire::DlfConverter(3pm) =head1 VERSION $Id: LrTimegroup.pm,v 1.5 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/SQLExt/Makefile.am0000644000175000017500000000313507744061520014763 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.2 2003/10/17 21:46:56 flacoste Exp $ ## Copyright (C) 2000-2001 Stichting LogReport Foundation LogReport@LogReport.org ## ## This file is part of Lire. ## ## Lire is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk SUBDIRS = allperllibdir = $(LR_PERL5LIBDIR)/Lire/SQLExt pm_s = \ LrCountUniq.pm \ LrFirst.pm \ LrLast.pm \ LrMatch.pm \ LrMissingCases.pm \ LrRangegroup.pm \ LrTimegroup.pm \ LrTimeslot.pm \ Registry.pm allperllib_DATA = $(pm_s) man_MANS = \ LrCountUniq.3pm \ LrFirst.3pm \ LrLast.3pm \ LrMatch.3pm \ LrMissingCases.3pm \ LrRangegroup.3pm \ LrTimegroup.3pm \ LrTimeslot.3pm \ Registry.3pm perlpackage = Lire::SQLExt transform = s,^,$(perlpackage)::, EXTRA_DIST = $(pm_s) CLEANFILES = $(man_MANS) lire-2.1.1/all/lib/Lire/SQLExt/Makefile.in0000644000175000017500000006156611677606132015014 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/include/rules.mk subdir = all/lib/Lire/SQLExt ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(allperllib_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" transform = s,^,$(perlpackage)::, ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done SUBDIRS = allperllibdir = $(LR_PERL5LIBDIR)/Lire/SQLExt pm_s = \ LrCountUniq.pm \ LrFirst.pm \ LrLast.pm \ LrMatch.pm \ LrMissingCases.pm \ LrRangegroup.pm \ LrTimegroup.pm \ LrTimeslot.pm \ Registry.pm allperllib_DATA = $(pm_s) man_MANS = \ LrCountUniq.3pm \ LrFirst.3pm \ LrLast.3pm \ LrMatch.3pm \ LrMissingCases.3pm \ LrRangegroup.3pm \ LrTimegroup.3pm \ LrTimeslot.3pm \ Registry.3pm perlpackage = Lire::SQLExt EXTRA_DIST = $(pm_s) CLEANFILES = $(man_MANS) all: all-recursive .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/Lire/SQLExt/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/Lire/SQLExt/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man3: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list=''; test -n "$(man3dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } install-allperllibDATA: $(allperllib_DATA) @$(NORMAL_INSTALL) test -z "$(allperllibdir)" || $(MKDIR_P) "$(DESTDIR)$(allperllibdir)" @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(allperllibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(allperllibdir)" || exit $$?; \ done uninstall-allperllibDATA: @$(NORMAL_UNINSTALL) @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(allperllibdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(allperllibdir)" && rm -f $$files # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-recursive all-am: Makefile $(MANS) $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-allperllibDATA install-man install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man3 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-allperllibDATA uninstall-man uninstall-man: uninstall-man3 .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \ ctags-recursive install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am check-local clean clean-generic \ ctags ctags-recursive distclean distclean-generic \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-allperllibDATA install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man3 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-allperllibDATA uninstall-am uninstall-man \ uninstall-man3 .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lire-2.1.1/all/lib/Lire/SQLExt/LrRangegroup.pm0000644000175000017500000000375510460672576015714 00000000000000package Lire::SQLExt::LrRangegroup; use strict; use POSIX qw/floor ceil/; sub lr_rangegroup { my ( $v, $start, $length, $min, $max ) = @_; return undef unless defined $v && defined $start && defined $length; $v = $min if defined $min && $v < $min; $v = $max if defined $max && $v > $max; return floor( ($v - $start) / $length ) * $length + $start; } sub lr_rangegroup_geo { my ( $v, $start, $length, $base, $min, $max ) = @_; return undef unless ( defined $v && defined $start && defined $length && defined $base ); $v = $min if defined $min && $v < $min; $v = $max if defined $max && $v > $max; return undef if $v < $start; my $range_start = $start; while ( $v < $range_start || $v >= ( $range_start + $length ) ) { $range_start += $length; $length *= $base; } return $range_start; } # keep perl high 1; =pod =head1 NAME Lire::SQLExt::LrRangegroup - FILL ME IN =head1 SYNOPSIS FILL ME IN =head1 DESCRIPTION FILL ME IN =head1 SEE ALSO Lire::DlfConverter(3pm) =head1 VERSION Id: LrRangegroup.pm,v 1.3 2003/10/14 12:59:55 wsourdeau Exp $ =head1 AUTHOR Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/SQLExt/LrMissingCases.pm0000644000175000017500000000265010460673257016161 00000000000000package Lire::SQLExt::LrMissingCases; use strict; sub new { return bless { '_count' => 0 }, shift; } sub step { my ( $self, @params ) = @_; foreach my $p ( @params ) { if ( ! defined $p ) { $self->{'_count'}++; last; } } return; } sub finalize { my $self = $_[0]; return $self->{'_count'}; } 1; __END__ =pod =head1 NAME Lire::SQLExt::LrMissingCases - FILL ME IN =head1 SYNOPSIS FILL ME IN =head1 DESCRIPTION FILL ME IN =head1 SEE ALSO Lire::DlfConverter(3pm) =head1 VERSION $Id: LrMissingCases.pm,v 1.3 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/SQLExt/LrFirst.pm0000644000175000017500000000571710460673257014667 00000000000000package Lire::SQLExt::LrFirst; use strict; sub new { my ( $class, $return_type ) = @_; # Copy if ( ref $class ) { return bless { %$class }, ref $class; } else { return bless { '_value' => undef, '_sort_str' => [], '_sort_values' => [], '_return' => $return_type || 'value', }, shift; } } sub is_number { my $str = $_[0]; no warnings 'numeric'; return ($str + 0 eq $str); } sub _init_keys { my ( $self, $value, @keys ) = @_; my @types = (); for ( my $i=0; $i < @keys; $i++ ) { return unless defined $keys[$i]; $types[$i] = is_number( $keys[$i] ) ? 0 : 1; } $self->{'_value'} = $value; $self->{'_sort_str'} = \@types; $self->{'_sort_values'} = \@keys; return; } sub step { my ( $self, $value, @keys ) = @_; return unless defined $value; unless ( @keys ) { $self->{'_value'} = $value unless defined $self->{'_value'}; return; } unless ( defined $self->{'_sort_str'}[0] ) { $self->_init_keys( $value, @keys ); return; } for ( my $i = 0; $i < @keys; $i++) { my $val = $keys[$i]; return undef unless defined $val; my $cmp_result; if ( ! $self->{'_sort_str'}[$i] && is_number( $val ) ) { $cmp_result = $val <=> $self->{'_sort_values'}[$i] } else { $self->{'_sort_str'}[$i] = 1; $cmp_result = $val cmp $self->{'_sort_values'}[$i] } return if $cmp_result == 1; last if $cmp_result == -1; } $self->{'_value'} = $value; $self->{'_sort_values'} = \@keys; return; } sub finalize { my $self = $_[0]; if ( $self->{'_return'} eq 'key' ) { return join( " ", @{$self->{'_sort_values'}} ); } else { return $self->{'_value'}; } } 1; __END__ =pod =head1 NAME Lire::SQLExt::LrFirst - FILL ME IN =head1 SYNOPSIS FILL ME IN =head1 DESCRIPTION FILL ME IN =head1 SEE ALSO Lire::DlfConverter(3pm) =head1 VERSION $Id: LrFirst.pm,v 1.4 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/SQLExt/LrLast.pm0000644000175000017500000000572610460673257014503 00000000000000package Lire::SQLExt::LrLast; use strict; sub new { my ( $class, $return_type ) = @_; # Copy if ( ref $class ) { return bless { %$class }, ref $class; } else { return bless { '_value' => undef, '_sort_str' => [], '_sort_values' => [], '_return' => $return_type || 'value', }, shift; } } sub is_number { my $str = $_[0]; no warnings 'numeric'; return ($str + 0 eq $str); } sub _init_keys { my ( $self, $value, @keys ) = @_; my @types = (); for ( my $i=0; $i < @keys; $i++ ) { return unless defined $keys[$i]; $types[$i] = is_number( $keys[$i] ) ? 0 : 1; } $self->{'_value'} = $value; $self->{'_sort_str'} = \@types; $self->{'_sort_values'} = \@keys; return; } sub step { my ( $self, $value, @keys ) = @_; return unless defined $value; unless ( @keys ) { $self->{'_value'} = $value; return; } unless ( defined $self->{'_sort_str'}[0] ) { $self->_init_keys( $value, @keys ); return; } for ( my $i = 0; $i < @keys; $i++) { my $val = $keys[$i]; return undef unless defined $val; my $cmp_result; if ( ! $self->{'_sort_str'}[$i] && is_number( $val ) ) { $cmp_result = $val <=> $self->{'_sort_values'}[$i] } else { $self->{'_sort_str'}[$i] = 1; $cmp_result = $val cmp $self->{'_sort_values'}[$i] } return if $cmp_result == -1; last if $cmp_result == 1; } $self->{'_value'} = $value; $self->{'_sort_values'} = \@keys; return; } sub finalize { my $self = $_[0]; if ( $self->{'_return'} eq 'key' ) { return join( " ", @{$self->{'_sort_values'}} ); } else { return $self->{'_value'}; } } 1; __END__ =pod =head1 NAME Lire::SQLExt::LrLast - FILL ME IN =head1 SYNOPSIS FILL ME IN =head1 DESCRIPTION FILL ME IN =head1 SEE ALSO Lire::DlfConverter(3pm) =head1 VERSION $Id: LrLast.pm,v 1.5 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/SQLExt/LrMatch.pm0000644000175000017500000000275010460673257014626 00000000000000package Lire::SQLExt::LrMatch; use strict; use Carp; use Lire::Utils qw/ check_param /; use vars qw/%RE_CACHE/; %RE_CACHE = (); sub lr_match { my ( $value, $re, $cs ) = @_; check_param( $re, 're' ); my $rx = $RE_CACHE{$re} ||= qr/$re/; return 0 unless defined $value; if ( $cs ) { return $value =~ /$re/; } else { return $value =~ /$re/i; } } 1; __END__ =pod =head1 NAME Lire::SQLExt::LrMatch - FILL ME IN =head1 SYNOPSIS FILL ME IN =head1 DESCRIPTION FILL ME IN =head1 SEE ALSO Lire::DlfConverter(3pm) =head1 VERSION $Id: LrMatch.pm,v 1.4 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHORS Francis J. Lacoste Wolfgang Sourdeau =head1 COPYRIGHT Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/DataTypes.pm0000644000175000017500000002515310460673254014051 00000000000000package Lire::DataTypes; use strict; use base qw/ Exporter /; use Carp; use vars qw/ @EXPORT_OK %EXPORT_TAGS %VALIDATORS /; BEGIN { @EXPORT_OK = qw/ check_xml_name check_nmtoken check_bool check_int check_number count2number number2count check_string eval_bool is_numeric_type is_quantity_type check_timestamp check_time check_date check_duration duration2sec sec2duration is_numeric_type is_time_type minutely_duration hourly_duration daily_duration weekly_duration monthly_duration yearly_duration check_ip check_port check_hostname check_url check_email check_bytes size2bytes bytes2size check_filename is_numeric_type check_superservice check_field check_chart check_type format_numeric_type /; }; use Lire::Config; # We don't set this at compile time, since the subs have to be defined # first %VALIDATORS = ( 'xml_name' => \&check_xml_name, 'nmtoken' => \&check_nmtoken, 'bool' => \&check_bool, 'int' => \&check_int, 'number' => \&check_number, 'string' => \&check_string, 'timestamp' => \&check_timestamp, 'date' => \&check_date, 'time' => \&check_time, 'duration' => \&check_duration, 'ip' => \&check_ip, 'port' => \&check_port, 'hostname' => \&check_hostname, 'url' => \&check_url, 'email' => \&check_email, 'bytes' => \&check_bytes, 'filename' => \&check_filename, 'type' => \&check_type, 'field' => \&check_field, 'superservice' => \&check_superservice, 'chart' => \&check_chart, ); # # XML Types # sub check_xml_name { unless (defined $_[0]) { warn "check_xml_name called with undef arg\n"; return undef; } return scalar $_[0] =~ /^[_a-zA-Z][-\w:.]*$/; } sub check_nmtoken { return scalar $_[0] =~ /\^[-\w:.]+$/; } # # Basic Types # sub check_bool { return scalar $_[0] =~ m!^(|0|1|true|false|yes|no|t|f)$!i } sub eval_bool { my $bool = $_[0]; if ( $bool =~ /^(1|true|yes|t)$/i) { return 1; } elsif ( $bool =~ /^(|0|false|no|n)$/i ) { return 0; } else { croak "invalid boolean value: $bool"; } return; } sub check_int { return scalar $_[0] =~ /^[-+]?\s*\d+$/; } sub check_string { return defined $_[0]; } sub check_number { return scalar $_[0] =~ /^[-+]?\s*\d+(\.\d+)?/; } sub count2number { my ($q, $unit ) = $_[0] =~ /^([.\d]+)\s*(([gG]igas?)?|([mM]egas?)?|([kK]ilos?)?)?/; if (! defined $unit) { return $q; } elsif ( $unit =~ /^m/i) { return $q * 1_000_000; } elsif ( $unit =~ /^g/i) { return $q * 1_000_000_000; } elsif ( $unit =~ /^k/i) { return $q * 1_000; } else { return $q; # Unknown units are interpreted as raw number } } sub number2count { my $number = $_[0]; # Prevent warnings with n/a or other such value return $number unless $number =~ /^[\d.]+$/; my ( $div, $units ); if ( $number >= 1_000_000_000 ) { $div = 1_000_000_000; $units = "G"; } elsif ($number >= 1_000_000 ) { $div = 1_000_000; $units = "M"; } elsif ( $number >= 1_000 ) { $div = 1_000; $units = "k"; } else { $div = 1; $units = ""; } my $q = $number / $div; my $int = int $q; my $rem = $q - $int; return $rem ? sprintf( "%.1f$units", $q ) : $int . $units; } # # Time Types # sub check_timestamp { return scalar check_string(); } sub check_time { return scalar check_string(); } sub check_date { return scalar check_string(); } sub check_duration { my $dur = $_[0]; return 0 unless defined $dur; return scalar $_[0] =~ /^\s*\d+\s* ((y(ears?)? )| # Years (M(onths?)? )| # Months (w(eeks?)? )| # Weeks (d(ays?)? )| # Days (h(ours?)? )| # Hours (m(inu?t?e?s?)?)| # Minutes (s(eco?n?d?s?)?))? # Seconds \s*$/x; } sub minutely_duration { return (defined $_[0] && $_[0] =~ /^(\d+)m(?:inu?t?e?s?)?$/ ) ? $1 : 0; } sub hourly_duration { return (defined $_[0] && $_[0] =~ /^(\d+)h(?:ours?)?$/ ) ? $1 : 0; } sub daily_duration { return (defined $_[0] && $_[0] =~ /^(\d+)d(?:ays?)?$/ ) ? $1 : 0; } sub weekly_duration { return (defined $_[0] && $_[0] =~ /^(\d+)w(?:eeks?)?$/ ) ? $1 : 0; } sub monthly_duration { return (defined $_[0] && $_[0] =~ /^(\d+)M(?:onths?)?$/ ) ? $1 : 0; } sub yearly_duration { return (defined $_[0] && $_[0] =~ /^(\d+)y(?:ears?)?$/ ) ? $1 : 0; } sub duration2sec { $_[0] =~ /^ (?:(\d+)y(?:ears?)? )?\s* # Years (?:(\d+)M(?:onths?)? )?\s* # Months (?:(\d+)w(?:eeks?)? )?\s* # Weeks (?:(\d+)d(?:ays?)? )?\s* # Days (?:(\d+)h(?:ours?)? )?\s* # Hours (?:(\d+)m(?:inu?t?e?s?)?)?\s* # Minutes (?:(\d+)(s(?:eco?n?d?s?)?)?)?\s* # Seconds $/x; my ( $years, $months, $weeks, $days, $hours, $mins, $secs ) = ( $1 || 0, $2 || 0, $3 || 0, $4 || 0, $5 || 0, $6 || 0, $7 || 0 ); my $s = 0; $s += $secs; $s += $mins * 60; $s += $hours * 60 * 60; $s += $days * 60 * 60 * 24; $s += $weeks * 60 * 60 * 24 * 7; $s += $months * 60 * 60 * 24 * 30; # Months and $s += $years * 60 * 60 * 24 * 365; # Years are approximation return $s; } sub sec2duration { my $sec = $_[0]; # Prevent warnings with n/a or other such value return $sec unless $sec =~ /^[\d.]+$/; my ( $div, $units ); if ( $sec >= 86400 ) { $div = 86400; $units = "d"; } elsif ($sec >= 3600 ) { $div = 3600; $units = "h"; } elsif ( $sec >= 60 ) { $div = 60; $units = "m"; } else { $div = 1; $units = "s"; } my $q = $sec / $div; my $int = int $q; my $rem = $q - $int; return $rem ? sprintf( "%.1f$units", $q ) : $int . $units; } # # Internet Types # sub check_ip { my @bytes = split /^\.$/, $_[0]; return 0 if @bytes != 4; for my $b ( @bytes ) { return 0 if $b < 0 || $b > 255; } return 1; } sub check_port { return 0 unless check_number(); # 2**16 = 65536 : 16 bit port field, cf Stevens, p4 return 0 if $_[0] < 0 || $_[0] > 65535; return 1; } sub check_hostname { return scalar $_[0] =~ /^[-\w]+(\.([-\w]+))*\.?$/; } sub check_url { return scalar check_string(); } sub check_email { return scalar check_string(); } # # Misc Types # sub check_bytes { return scalar $_[0] =~ /^[.\d]+\s*([mM](egs?)?|[kK]|[gG](igas?)?)?/; } sub size2bytes { my ($q, $unit ) = $_[0] =~ /^([.\d]+)\s*([mM](egs?)?|[kK]|[gG](igas?)?)?/; if (! defined $unit) { return $q; } elsif ( $unit =~ /^m/i) { return $q * 1024 * 1024; } elsif ( $unit =~ /^g/i) { return $q * 1024 * 1024 * 1024; } elsif ( $unit =~ /^k/i) { return $q * 1024; } else { return $q; # Unknown units are interpreted as bytes } } use constant GIG => 1024 ** 3; use constant MEG => 1024 ** 2; use constant K => 1024; sub bytes2size { my $bytes = $_[0]; # Prevent warnings with n/a or other such value return $bytes unless $bytes =~ /^[\d.]+$/; my ( $div, $units ); if ( $bytes >= GIG ) { $div = GIG; $units = "G"; } elsif ($bytes >= MEG ) { $div = MEG; $units = "M"; } elsif ( $bytes >= K ) { $div = K; $units = "k"; } else { $div = 1; $units = ""; } my $q = $bytes / $div; my $int = int $q; my $rem = $q - $int; return $rem ? sprintf( "%.1f$units", $q ) : $int . $units; } sub check_filename { return scalar check_string(); } # # Special Types # sub check_type { return 0 unless defined $_[0]; return scalar $_[0] =~ /^(id|bool|int|number|string # Basic |timestamp|time|date|duration # Time |ip|port|hostname|url|email # Internet |bytes|filename # Misc |type|field|superservice|chart # Special )$/x; } sub check_field { return scalar check_xml_name( @_ ); } sub check_superservice { return scalar $_[0] =~ /^\w+$/; } sub check_chart { return scalar $_[0] =~ /^(bars|lines|pie|histogram)$/; } sub is_time_type { return scalar $_[0] =~ /^(timestamp|time|date)$/; } sub is_numeric_type { return scalar is_time_type( @_ ) || scalar is_quantity_type( @_ ); } sub is_quantity_type { return scalar $_[0] =~ /^(bytes|int|number|duration)$/; } sub format_numeric_type { my ($value, $type) = @_; return 'NaN' unless defined $value; $type ||= "number"; my $fmt_value = $value; if ( $type eq 'bytes' ) { $fmt_value = bytes2size( $value ) if Lire::Config->get( 'lr_scale_bytes' ); } elsif ( $type eq 'duration' ) { $fmt_value = sec2duration( $value ) if Lire::Config->get( 'lr_scale_seconds' ); } elsif ( Lire::Config->get( 'lr_scale_numbers' ) ) { $fmt_value = number2count( $value ); } return $fmt_value; } # keep perl happy 1; __END__ =pod =head1 NAME Lire::DataTypes - check wether value is of declared type =head1 SYNOPSIS use Lire::DataTypes qw/ size2bytes duration2sec ... /; $bytes = size2bytes( $min_value ); $sec = duration2sec( $max_value ); ... =head1 DESCRIPTION Lire::DataTypes offers several routines, like check_url and check_duration, to decide wether a value is of a Lire type. Furthermore, routines to process these types, like duration2sec and bytes2size are offered. Lire types are defined in lire-types.mod. This module is widely used throughout other Lire:: modules. =head1 AUTHOR Francis J. Lacoste =head1 VERSION $Id: DataTypes.pm,v 1.44 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/Report/0000755000175000017500000000000011677607767013163 500000000000000lire-2.1.1/all/lib/Lire/Report/ColumnInfo.pm0000644000175000017500000001601010460673257015472 00000000000000package Lire::Report::ColumnInfo; use strict; use Carp; use POSIX qw/ ceil /; use Lire::DataTypes qw/ check_type check_xml_name /; use Lire::Utils qw/ check_param check_object_param /; =pod =head1 NAME Lire::Report::ColumnInfo - Object that holds column meta-data. =head1 SYNOPSIS my $info = $subreport->column_info_by_idx( 0 ); print "Column's name: ", $info->name(), "\n"; print "Column's index: ", $info->index(), "\n"; print "Column's type: ", $info->type(), "\n"; print "Column's label: ", $info->label(), "\n"; =head1 DESCRIPTION The Lire::Report::ColumnInfo object contains meta-data information on the columns of a subreport. =head1 CONSTRUCTOR =head2 new( $group, $name, $class, $type, [$label]]) Creates a new Lire::Report::ColumnInfo object. The column info attributes are initialized based on $name, $class, $type and $label. =cut sub new { my ( $class, $group, $name, $type_class, $type, $label ) = @_; check_object_param( $group, 'group_info', 'Lire::Report::GroupInfo' ); check_param( $name, 'name', \&check_xml_name, "'name' parameter isn't a valid XML name" ); check_param( $type_class, 'class', qr/^(numerical|categorical)$/, "'class' parameter should either be 'numerical' or 'categorical'" ); check_param( $type, 'type', \&check_type, "'type' parameter isn't a valid Lire type" ); my $self = bless { 'name' => $name, 'class' => $type_class, 'type' => $type, 'col_width' => 0, 'max_chars' => undef, 'avg_chars' => undef, 'padding' => 0, 'index' => undef, 'group_info' => $group, }, $class; $self->label( $label ) if ( defined $label ); return $self; } =pod =head1 OBJECT METHODS =pod =head2 name() Returns the name of this column. This name can be used to find the group operation (from the report specification) that is responsible for the column's content. =cut sub name { return $_[0]{'name'}; } =pod =head2 class() Returns the column's class of data. This will be either 'numerical' or 'categorical'. =cut sub class { return $_[0]{'class'}; } =pod =head2 type() Returns the column's type. This referes to the type of the DLF field that was usd to generate this column's values. =cut sub type { return $_[0]{'type'}; } =pod =head2 group_info() Returns the GroupInfo object which contains this column. =cut sub group_info { return $_[0]{'group_info'}; } =pod =head2 index() Returns the column's index in the table. This will be undef until the column info object is added to a Lire::Subreport or Lire::Group object. =cut sub index { $_[0]{'index'} = $_[1] if @_ == 2; return $_[0]{'index'}; } =pod =head2 col_start() Returns the display column which is the start of the cell span that should be used to render this column's values. =cut sub col_start { $_[0]{'col_start'} = $_[1] if @_ == 2; return $_[0]{'col_start'}; } =pod =head2 col_end() Returns the display column which is the end of the cell span that should be used to render this column's values. =cut sub col_end { $_[0]{'col_end'} = $_[1] if @_ == 2; return $_[0]{'col_end'}; } =pod =head2 col_width() Returns the suggested column width for this column in characters. =cut sub col_width { $_[0]{'col_width'} = $_[1] if @_ == 2; return $_[0]{'col_width'}; } =pod =head2 max_chars() This method returns the length of the longest string in that column (including the label). =cut sub max_chars { my $self = $_[0]; $self->{'max_chars'} = $_[1] if @_ == 2; croak "max_chars() called while stat is undefined. Was subreport's finalize() called?" unless defined $self->{'max_chars'}; return $self->{'max_chars'}; } =pod =head2 avg_chars() This method returns the average length of strings in that column (including the label). This will be round up to the next integer (1.3 -> 2). =cut sub avg_chars { my $self = $_[0]; $self->{'avg_chars'} = $_[1] if @_ == 2; croak "avg_chars() called while stat is undefined. Was subreport's finalize() called?" unless defined $self->{'avg_chars'}; return $self->{'avg_chars'}; } sub init_chars_stats { my ( $self ) = @_; $self->{'total_chars'} = 0; $self->{'column_count'} = 0; $self->{'max_chars'} = length( $self->label() ); return; } sub update_chars_stats { my ( $self, $value ) = @_; my $len = length $value; $self->{'total_chars'} += $len; $self->{'column_count'}++; $self->{'max_chars'} = $len if $len > $self->{'max_chars'}; return; } sub finish_chars_stats { my $self = $_[0]; my $len = length $self->label(); $self->{'avg_chars'} = ceil( ($self->{'total_chars'} + $len) / ($self->{'column_count'} + 1) ); delete $self->{'total_chars'}; delete $self->{'column_count'}; return; } =pod =head2 label( [$label] ) Returns the column's label. If the $label parameter is defined, the column's label will be set to this new value. =cut sub label { my ( $self, $label ) = @_; $self->{'label'} = $label if ( @_ == 2 ); return ( $self->{'label'} ? $self->{'label'} : $self->{'name'} ); } sub write_report { my ( $self, $fh, $indent ) = @_; $fh ||= *STDOUT; my $pfx = ' ' x $indent; print $fh $pfx, qq{{'label'}; print $fh qq{ max-chars="$self->{'max_chars'}" avg-chars="}, $self->avg_chars, qq{"/>\n}; return; } #------------------------------------------------------------------------ # Method delete() # # Remove circular references sub delete { my ( $self ) = @_; %$self = (); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Report::Subreport(3pm) Lire::Report::GroupInfo(3pm) =head1 VERSION $Id: ColumnInfo.pm,v 1.15 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/Report/Group.pm0000644000175000017500000002743510460673257014532 00000000000000package Lire::Report::Group; use strict; use Carp; use Lire::Report::Entry; use Lire::Utils qw/ check_param check_object_param tree_apply /; =pod =head1 NAME Lire::Report::Group - Object that include subgroups and other entries. =head1 SYNOPSIS foreach my $e ( $group->entries() ) { # Process entries' data. } =head1 DESCRIPTION The Lire::Report::Group object contains entries grouped together in a subreport. =head1 CONSTRUCTOR You create new Lire::Report::Group object by calling the create_group() method on one Lire::Report::Entry object. =cut sub new { my ( $class, $entry, $group_info ) = @_; check_object_param( $entry, 'entry', 'Lire::Report::Entry' ); check_object_param( $group_info, 'group_info', 'Lire::Report::GroupInfo' ); return bless( { 'type' => 'group', 'entries' => [], 'summary' => {}, 'nrecords' => 0, 'missing_cases' => 0, 'show' => undef, 'parent_entry' => $entry, 'group_info' => $group_info, 'row_idx' => undef }, $class ); } =pod =head1 OBJECT METHODS =head2 parent_entry() Returns the entry in which this goup is contained. This will be undef for the Subreport since it's not contained in any entry. =cut sub parent_entry { return $_[0]{'parent_entry'}; } =pod =head2 group_info() Returns the Lire::Report::GroupInfo which contains the information describing the entries of this group. =cut sub group_info { return $_[0]{'group_info'} } =pod =head2 subreport() Returns the Lire::Report::Subreport object in which this entry is =cut sub subreport { return $_[0]->parent_entry->subreport(); } =pod =head2 row_idx() Returns the row index in the table body where this group's summary should be displayed. If undef, this group isn't displayed. =cut sub row_idx { $_[0]{'row_idx'} = $_[1] if @_ == 2; return $_[0]{'row_idx'}; } sub assign_row_indices { my ( $self, $nrow_idx ) = @_; $self->{'row_idx'} = $nrow_idx++; my $count = 1; foreach my $e ( @{$self->{'entries'}} ) { last if (defined $self->{'show'} && $count > $self->{'show'} ); $e->row_idx( $nrow_idx ); my $max = $nrow_idx; foreach my $group ( $e->data() ) { next unless UNIVERSAL::isa( $group, 'Lire::Report::Group' ); my $tmp_idx = $group->assign_row_indices( $nrow_idx ); $max = $tmp_idx if ($tmp_idx > $max); } $nrow_idx = $max + 1; $count++; } return $nrow_idx - 1; } sub compute_column_info_stats { my $self = $_[0]; $self->_init_chars_stats(); $self->_update_chars_stats(); $self->_finish_chars_stats(); return; } sub _init_chars_stats { my $self = $_[0]; tree_apply( $self->group_info(), sub { return $_[0]->isa( 'Lire::Report::GroupInfo' ) ? [ $_[0]->children() ] : [] }, sub { my $child = $_[0]; $child->init_chars_stats() if $child->isa( 'Lire::Report::ColumnInfo' ); return; } ); return; } sub _update_chars_stats { my $self = $_[0]; my $count = 1; my $max = $self->{'show'}; foreach my $sum ( values %{$self->{'summary'}} ) { $sum->{'col_info'}->update_chars_stats( $sum->{'content'} ); } foreach my $entry ( @{$self->{'entries'}} ) { last if $max && $count++ > $max; foreach my $child ( $entry->data() ) { if ( UNIVERSAL::isa( $child, 'Lire::Report::Group' ) ) { $child->_update_chars_stats(); } else { $child->{'col_info'}->update_chars_stats( $child->{'content'}); } } } return; } sub _finish_chars_stats { my $self = $_[0]; tree_apply( $self->group_info(), sub { return( $_[0]->isa( 'Lire::Report::GroupInfo' ) ? [ $_[0]->children() ] : [] ) }, sub { my $child = $_[0]; $child->finish_chars_stats() if $child->isa( 'Lire::Report::ColumnInfo' ); return; } ); return; } =pod =head2 show( [$show] ) Returns the number of entries that should be displayed in the formatted report. There may be more entries than that in the group. When this parameter is zero or undefined, all available entries should be displayed. If the $show is parameter is set, the group's show parameter will be set to this new value. =cut sub show { $_[0]{'show'} = $_[1] if @_ == 2; return $_[0]{'show'}; } =pod =head2 nrecords( [$n] ) Returns the number of DLF records that were included in this group. =cut sub nrecords { if ( @_ == 2 ) { $_[0]{'nrecords'} = defined $_[1] ? $_[1] : 0; } return $_[0]{'nrecords'}; } =pod =head2 missing_cases( [$n] ) Returns the number of DLF records that contained missing cases which prevent them from being unclude in the subreport. =cut sub missing_cases { if ( @_ == 2 ) { $_[0]{'missing_cases'} = defined $_[1] ? $_[1] : 0; } return $_[0]{'missing_cases'}; } =pod =head2 summary_values() Returns the summary values of this group. This is an array of hash reference like the ones returnes by the values() method described in Lire::Report::Entry(3pm). =cut sub summary_values { my $self = $_[0]; # Sort the columns according to column info's index. return sort { $a->{'col_info'}->index() <=> $b->{'col_info'}->index() } values %{$self->{'summary'}}; } =pod =head2 get_summary_value( $name ) Returns the summary value of the operator $name. This is an hash reference like is returned by the values() method described in Lire::Report::Entry(3pm). Returns undef if the summary value wasn't computed for operator $name. =cut sub get_summary_value { return $_[0]->{'summary'}{$_[1]}; } =pod =head2 set_summary_value( $name, %value ) Sets the value of the operator $name computed over all the DLF records of the group. Consult the add_value() method in Lire::Report::Entry(3pm) for information on the parameters. =cut sub set_summary_value { my ( $self, $name, %value ) = @_; check_param( $name, 'name' ); $value{'content'}= "" unless defined $value{'content'}; $value{'value'}= $value{'content'} unless defined $value{'value'}; my $info = $self->{'group_info'}->column_info_by_name( $name ); croak "there is no column named '$name'" unless $info; croak( "Operator $name is an aggregator" ) unless $info->isa( "Lire::Report::ColumnInfo" ); $value{'type'} = 'value'; $value{'col_info'} = $info; $value{'n'} = undef unless exists $value{'n'}; $value{'total'} = undef unless exists $value{'total'}; $value{'missing_cases'} = 0 unless defined $value{'missing_cases'}; $self->{'summary'}{$name} = \%value; return; } =pod =head2 entries() Returns the entries in the group. =cut sub entries { return @{$_[0]{'entries'}}; } =pod =head2 create_entry() Adds a data entry to this group. This will create a new Lire::Report::Entry object which can then be filled with data. =cut sub create_entry { my $self = $_[0]; my $entry = new Lire::Report::Entry( $self ); push @{$self->{'entries'}}, $entry; return $entry; } =pod =head2 find_entry( $name, $dlf ) =cut sub find_entry { my ( $self, $name, $dlf ) = @_; my $key_names = $self->{'group_info'}->categorical_names(); foreach my $n ( @$key_names ) { return undef if ! defined $dlf->{$n}; } my $entry = undef; ENTRY: foreach my $e ( @{$self->{'entries'}} ) { foreach my $n ( @$key_names ) { next ENTRY unless ( $e->data_by_name( $n )->{'value'} eq $dlf->{$n} ); } $entry = $e; last ENTRY; } return undef unless defined $entry; return $entry if $name eq $self->{'group_info'}->name(); return $self->_find_entry_in_group_children( $name, $dlf, $entry ); } sub _find_entry_in_group_children { my ( $self, $name, $dlf, $entry ) = @_; foreach my $c ( $entry->data() ) { if ( UNIVERSAL::isa( $c, 'Lire::Report::Group' ) ) { my $e = $c->find_entry( $name, $dlf ); return $e if defined $e; } } return undef; } # ------------------------------------------------------------------------ # Method write_report( [$fh, [$index]] ) # sub write_report { my ( $self, $fh, $indent ) = @_; $fh ||= *STDOUT; my $pfx = ' ' x $indent; print $fh $pfx, "{'show'}; print $fh ">\n"; $self->write_group_summary( $fh, $indent + 1); foreach my $e ( $self->entries ) { $e->write_report( $fh, $indent + 1 ); } print $fh $pfx, "\n"; return; } # # helper method for Lire::Report::Subreport::last_row_idx() # sub _last_row_idx { my $self = $_[0]; my $i = $#{$self->{'entries'}}; while ( $i >= 0 ) { my $last_idx = $self->{'entries'}[$i]->_last_row_idx(); return $last_idx if defined $last_idx; $i--; } return undef; } # # helper method for Lire::Report::Subreport::getrow_by_idx # sub _getrow_by_idx { my ( $self, $idx, $row ) = @_; for ( my $i = $#{$self->{'entries'}}; $i >= 0; $i-- ) { next unless defined $self->{'entries'}[$i]->row_idx(); if ( $self->{'entries'}[$i]->row_idx() <= $idx ) { $self->{'entries'}[$i]->_getrow_by_idx( $idx, $row ); return; } } return; } # ------------------------------------------------------------------------ # write_group_summary( $fh, $indent ) # # Write the group-summary element for this group sub write_group_summary { my ( $self, $fh, $indent ) = @_; my $pfx = ' ' x $indent; print $fh $pfx, qq!{'row_idx'}; print $fh ">\n"; foreach my $value ( $self->summary_values() ) { Lire::Report::Entry::write_value( $fh, $pfx . ' ', $value ); } print $fh $pfx, "\n"; return; } #------------------------------------------------------------------------ # Method delete() # # Remove circular references sub delete { my $self = $_[0]; $self->{'group_info'}->delete(); foreach my $entry ( @{$self->{'entries'}} ) { $entry->delete(); } %$self = (); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::ReportParser::ReportBuilder(3pm) Lire::Report(3pm) Lire::Report::Subreport(3pm) Lire::Report::Entry(3pm) Lire::Report::ChartConfig(3pm) Lire::Report::Section(3pm) =head1 VERSION $Id: Group.pm,v 1.33 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/Report/Subreport.pm0000644000175000017500000003102110460673257015405 00000000000000package Lire::Report::Subreport; use strict; use base qw/ Lire::Report::Group /; use Carp; use POSIX qw/ strftime /; use Lire::DataTypes qw/ check_xml_name check_chart /; use Lire::Utils qw/ xml_encode check_param check_object_param /; use Lire::ReportSpec; =pod =head1 NAME Lire::Subreport - Interface to a Lire subreport. =head1 SYNOPSIS use Lire::ReportParser::ReportBuilder; my $parser = new Lire::ReportParser::ReportBuilder; my $report = $parser->parse( "report.xml" ); foreach my $s ( $report->sections() ) { print "Section: '", $s->title(), "\n\n"; foreach my $r ( $s->subreports() ) { print "Subreport ", $r->title(), " has ", scalar $r->entries(), " entries\n"; } } =head1 DESCRIPTION This module offers an API to the subreports included in the sections of a Lire's report. This object has all the methods that the Lire::Report::Group(3pm) object offers. You'll find more information on to access the data contained in a subreport in that man page. =head1 CONSTRUCTORS =head2 new( $superservice, $type) Creates a new Lire::Report::Subreport object. The $superservice parameter and $type parameters defines the report specification which was used to generate this subreport's data. =cut sub new { my ( $class, $superservice, $type ) = @_; check_param( $superservice, 'superservice', \&check_xml_name, "invalid superservice's name" ); check_param( $type, 'type', \&check_xml_name, 'invalid type' ); return bless( { 'superservice' => $superservice, 'type' => $type, 'entries' => [], 'missing' => 0, 'summary' => {}, 'parent_entry' => undef, 'nrecords' => 0, 'missing_cases' => 0, 'row_idx' => undef, 'title' => undef, 'description' => undef, 'show' => undef, '_schemas' => undef, '_chart_configs' => [], }, $class ); } =pod =head2 new_missing( $superservice, $type, [$reason]) Creates a new Lire::Report::Subreport object marked as missing. The $superservice parameter and $type parameters defines the report specification which was used to generate this subreport's data. The $reason parameter sets the reason why this subreport is missing. =cut sub new_missing { my ( $class, $superservice, $type, $reason ) = @_; check_param( $superservice, 'superservice', \&check_xml_name, "invalid superservice's name" ); check_param( $type, 'type', \&check_xml_name, 'invalid type' ); return bless( { 'superservice' => $superservice, 'type' => $type, 'missing' => 1, 'entries' => [], 'reason' => $reason }, $class ); } =pod =head1 OBJECT METHODS =head2 id( [ $new_id ] ) Returns (and optionnally change) the id of this subreport. The subreport's ID uniquely identify it in its Report. Subreports with the same ID will be merged together. =cut sub id { my ( $self, $id ) = @_; if ( @_ == 2 ) { check_param( $id, 'id', \&check_xml_name, 'ID should be a valid XML name' ); $self->{'_id'} = $id; } return $self->{'_id'}; } =pod =head2 is_missing() Returns true if this subreport was marked as missing in the XML file. A missing subreport is a subreport which was present in the report configure file but which was marked as missing in the XML report. This happens when the report specification requires fields that weren't available in the DLF files generated. It can also happen when an error occurs in the report generation process. =cut sub is_missing { return $_[0]{'missing'}; } =pod =head2 missing_reason() Reports why the subreport is missing. This will be undefined when the subreport is not missing. =cut sub missing_reason { return $_[0]{'reason'}; } =pod =head2 superservice() Returns the superservice of this subreport. This is the superservice that defined the report specification from which the subreport was generated. =cut sub superservice { return $_[0]{'superservice'}; } =pod =head2 type() Returns the type of this subreport. This is the ID of the report specification that was used to generate this subreport. =cut sub type { return $_[0]{'type'}; } =pod =head2 schemas( [ $schema, ... ] ) Returns the schemas used by this Subreport. =cut sub schemas { my $self = shift; if ( @_ ) { $self->{'_schemas'} = [ @_ ]; } if ( ! $self->{'_schemas'} ) { my $spec = Lire::ReportSpec->load( $self->{'superservice'}, $self->{'type'} ); $self->{'_schemas'} = [ @{ $spec->schemas() } ]; } return $self->{'_schemas'}; } =cut =pod =head2 field_schema( $field ) Returns the schema which contain field $field. Returns undef if this name isn't defined in any schema. =cut sub field_schema { my ( $self, $field ) = @_; check_param( $field, 'field' ); foreach my $s ( @{ $self->schemas() } ) { return $s if ( Lire::DlfSchema::load_schema( $s )->has_field( $field)); } return undef; } =pod =head2 chart_configs() Returns an array reference containing Lire::Report::ChartConfig objects specifying the charts that should be generated from this Subreport. =cut sub chart_configs { return $_[0]{'_chart_configs'}; } =pod =head2 add_chart_config( $chart_config ) Adds a Lire::Report::ChartConfig object specifying a chart that should be generated from this Subreport's data. =cut sub add_chart_config { my ( $self, $chart_config ) = @_; check_object_param( $chart_config, 'chart_config', 'Lire::Report::ChartConfig' ); push @{$self->{'_chart_configs'}}, $chart_config; return; } =pod =head2 title( [$title] ) Returns the subreport's title. If the $title is parameter is set, the subreport's title will be set to this new value. =cut sub title { $_[0]{'title'} = $_[1] if defined $_[1]; return $_[0]{'title'}; } =pod =head2 description( [$new_desc] ) Returns this subreport's description. The description is encoded in DocBook XML. If the $description parameter is set, this method will set this subreport's description to this new value. If the $description parameter is undef, that description will be removed. =cut sub description { $_[0]->{'description'} = $_[1] if @_ == 2; return $_[0]->{'description'}; } =pod =head2 table_info( [$table_info] ) Returns the top-level Lire::Report::TableInfo object describing this table layout. If $table_info parameter is set, the subreport table info will be set to this object. =cut sub table_info { my ( $self, $info ) = @_; if ( @_ == 2 ) { croak ( "can't change table_info once entries were added" ) if @{$self->{'entries'}}; check_object_param( $info, 'info', "Lire::Report::TableInfo" ); $self->{'table_info'} = $info; $self->{'group_info'} = $info; } return $self->{'table_info'}; } =pod =head2 nrows() Returns the number of rows in the table. =cut sub nrows { my $self = $_[0]; return $self->{'_nrows'} if defined $self->{'_nrows'}; my $last_idx = $_[0]->_last_row_idx(); return $self->{'_nrows'} = defined $last_idx ? $last_idx + 1 : 0; } =pod =head2 last_row_idx() Returns the index of the last row of data. =cut sub last_row_idx { return $_[0]->nrows() - 1; } =pod =head2 getrow_by_idx( $index ) Returns an array reference containing row 'idx' of the subreport data. A row will contain all the values (categorical and numerical) that would appear on the same row. When an entry is made of categorical variables plus nested groups, the group's summary values will appear on the same row than the categorical variable. Each value is the hash reference that is returned by Entry::data_by_name() for that column and it is in the row at the column's index. =cut sub getrow_by_idx { my ( $self, $idx ) = @_; check_param( $idx, 'idx', qr/^-?[0-9]+$/, "'idx' parameter should be an integer" ); croak "index out of bounds: $idx" if ( $idx < 0 ? $idx < -$self->nrows() : $idx > $self->last_row_idx() ); $idx = $self->nrows() + $idx if $idx < 0; my $row = []; $self->_getrow_by_idx( $idx, $row ); return $row; } =pod =head2 getrows() Returns all rows contained in the subreport. This method is useful for rendering the subreport table. =cut sub getrows { my $self = $_[0]; my @rows; for ( my $i = 0; $i < $self->_last_row_idx() + 1; $i++ ) { push @rows, $self->getrow_by_idx( $i ); } return \@rows; } =pod =head2 finalize() This method should be called after all entries were added. It assign row-idx and computes column width and statistics. =cut sub finalize { my $self = $_[0]; $self->assign_row_indices(); $self->compute_column_info_stats(); $self->{'table_info'}->compute_columns_width(); return; } sub assign_row_indices { my ( $self, $start ) = @_; # Prevent infinite recursion as parent call back this # implementation return $self->SUPER::assign_row_indices( $start ) if defined $start; my $idx = $self->assign_row_indices( -1 ); $self->{'row_idx'} = undef; return $idx; } # Overrides Lire::Report::Group::subreport sub subreport { return $_[0]; } sub write_report { my ( $self, $fh, $indent ) = @_; $fh ||= *STDOUT; my $pfx = ' ' x $indent; my $schemas = join( " ", @{ $self->schemas() } ); if ( $self->{'missing'} ) { print $fh qq!$pfx\n\n!; } else { print $fh qq!$pfx\n!; print $fh "$pfx ", xml_encode( $self->{'title'} ), "\n\n"; if ( $self->description() ) { print $fh "$pfx "; print $fh $self->description(), "\n\n"; } print $fh "$pfx {'show'}; print $fh ">\n"; $self->table_info()->write_report( $fh, $indent + 2 ); $self->write_group_summary( $fh, $indent + 2 ); foreach my $e ( $self->entries() ) { $e->write_report( $fh, $indent + 2 ); } print $fh "$pfx \n"; if ( @{$self->{'_chart_configs'}} ) { print $fh "$pfx \n"; foreach my $cfg ( @{$self->{'_chart_configs'}} ) { $cfg->save_xml( $fh, $indent + 1, 'lrcml:' ); } print $fh "$pfx \n\n"; } print $fh "$pfx\n\n"; } return; } #------------------------------------------------------------------------ # Method delete() # # Remove circular references sub delete { my $self = $_[0]; $self->{'table_info'}->delete() if $self->{'table_info'}; foreach my $e ( $self->entries() ) { $e->delete(); } return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::ReportParser::ReportBuilder(3pm) Lire::Report::Section(3pm) Lire::Report::Report(3pm) Lire::Report::Entry(3pm), Lire::Report::Group(3pm), Lire::Report::ChartConfig(3pm) =head1 VERSION $Id: Subreport.pm,v 1.46 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/Report/Section.pm0000644000175000017500000001014210460673257015025 00000000000000package Lire::Report::Section; use strict; use Carp; use Lire::Utils qw/ xml_encode check_object_param /; =pod =head1 NAME Lire::Section - Interface to the content of the section's element. =head1 SYNOPSIS my $section = Lire::ReportParser::ReportBuilder( "report.xml" ); foreach my $s ( $report->sections() ) { print "Section: '", $s->title(), "' has ", scalar $s->subreports(), " subreports in it\n"; } =head1 DESCRIPTION This class offers an API to the section's elements of a Lire report. =head1 CONSTRUCTOR =head2 new( [$title] ) Creates a new Lire::Report::Section. The section's title will be set to the $title parameter if present. =cut sub new { my ( $class, $title ) = @_; return bless( { '_title' => $title || "Untitled", '_subreports' => [] }, $class ); } =pod =head1 OBJECT METHODS =head2 title( [$title] ) Returns the section's title, if it has one. The section's title will be changed $title if that parameter is set. =cut sub title { $_[0]{'_title'} = $_[1] if ( @_ == 2 ); return $_[0]{'_title'}; } =pod =pod =head2 description( [$description] ) Returns this section's description. The description is encoded in DocBook XML. If the $description parameter is set, this method will set this section's description to this new value. If the $description parameter is undef, that description will be removed. =cut sub description { $_[0]{'_description'} = $_[1] if ( @_ == 2 ); return $_[0]->{'_description'}; } =pod =head2 subreports() Returns the subreport's included in that section. This will be an array of Lire::Report::Subreport objects. =cut sub subreports { return @{$_[0]{'_subreports'}}; } =pod =head2 add_subreport( $subreport ) Adds a subreport to this report. The $subreport parameter should be a Lire::Report::Subreport object. =cut sub add_subreport { my ( $self, $subreport ) = @_; check_object_param( $subreport, 'subreport', 'Lire::Report::Subreport' ); croak "can't add a Subreport which doesn't have an id" unless $subreport->id(); push @{$self->{'_subreports'}}, $subreport; return; } =pod =head2 subreports_by_type( $type ) Returns all the subreports in this section of a the type $type. The subreport's type is the id of the report specification used to compute the reports. The subreports are returned as an array of Lire::Report::Subreport objects. =cut sub subreports_by_type { return grep { $_->type() eq $_[1] } $_[0]->subreports(); } sub write_report { my ( $self, $fh, $indent ) = @_; $fh ||= *STDOUT; my $pfx = ' ' x $indent; print $fh qq"$pfx\n"; print $fh "$pfx ", xml_encode( $self->{'_title'} ), "\n\n"; if ( $self->description() ) { print $fh "$pfx "; print $fh $self->description, "\n\n"; } foreach my $r ( $self->subreports() ) { $r->write_report( $fh, $indent + 1 ); } print $fh "$pfx\n"; return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::ReportParser::ReportBuilder(3pm) Lire::Report(3pm) Lire::Report::Subreport(3pm) Lire::Report::Entry(3pm) Lire::Report::Group(3pm) =head1 VERSION $Id: Section.pm,v 1.16 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/Report/ChartConfig.pm0000644000175000017500000000772710460673257015627 00000000000000package Lire::Report::ChartConfig; use strict; use base qw/ Lire::Config::Dictionary /; use Lire::Utils qw/check_object_param/; use Carp; =pod =head1 NAME Lire::Report::ChartConfig - Chart configuration object. =head1 SYNOPSIS use Lire::Report::ChartConfig; my $chart = new Lire::Report::ChartConfig(); $chart->title( 'Downloads by Visits Scatterplot' ) $chart->type( Lire::PluginManager->get_plugin( 'chart_type', 'scatterplot' ); ... =head1 DESCRIPTION This is a Lire::Config::Dictionary subclass which is used to define a chart that will be generated from a Lire::Report::Subreport. =head1 CONSTRUCTOR =head2 new() Creates a new Lire::Report::ChartConfig object. =head1 ATTRIBUTES These are methods that wraps around the Lire::Config::Dictionary get() and set() method. =head2 basename( [ $new_basename ] ) Returns (and optionnally changes) the Chart's basename. =head2 title( [ $new_title ] ) Returns (and optionnally changes) the Chart's title. =head2 type( [ $new_type ] ) Returns (and optionally changes) the ChartType plugin used by this Config. =head2 type_properties() Returns the Lire::Config::Value object used to store the ChartType's specific properties. =head2 case_var() Returns the Lire::Report::ColumnInfo object that is use to select the cases that will be part of the chart's data. =head2 xlabel( [ $new_xlabel ] ) Returns (and optionnally change) the Chart's X axis label.. =head2 ylabel( [ $new_ylabel ] ) Returns (and optionnally change) the Chart's Y axis label.. =cut sub new { my ( $class, %params ) = @_; $params{'spec'} ||= new Lire::Config::ChartSpec( 'name' => 'chart' ); check_object_param( $params{'spec'}, 'spec', 'Lire::Config::ChartSpec' ); return $class->SUPER::new( %params ); } sub basename { my ( $self, $new_name ) = @_; if ( @_ == 2 ) { $self->get( 'name' )->set( $new_name ); } return $self->get( 'name' )->as_value(); } sub title { my ( $self, $new_title ) = @_; if ( @_ == 2 ) { $self->get( 'title' )->set( $new_title ); } return $self->get( 'title' )->as_value(); } sub xlabel { my ( $self, $new_xlabel ) = @_; if ( @_ == 2 ) { $self->get( 'xlabel' )->set( $new_xlabel ); } return $self->get( 'xlabel' )->as_value(); } sub ylabel { my ( $self, $new_ylabel ) = @_; if ( @_ == 2 ) { $self->get( 'ylabel' )->set( $new_ylabel ); } return $self->get( 'ylabel' )->as_value(); } sub type { my ( $self, $new_type ) = @_; if ( @_ == 2 ) { check_object_param( $new_type, 'type', 'Lire::ChartType' ); $self->get( 'type' )->set_plugin( $new_type->name() ); } return Lire::PluginManager->get_plugin( 'chart_type', $self->get( 'type' )->get_plugin() ); } sub type_properties { my $self = $_[0]; return $self->get( 'type' )->get_properties(); } sub case_var { my $self = $_[0]; return $self->get( 'case_var' )->as_value(); } sub as_value { return $_[0]; } 1; __END__ =pod =head1 SEE ALSO Lire::Config::ChartSpec(3pm) Lire::ChartType(3pm) =head1 VERSION $Id: ChartConfig.pm,v 1.7 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/Report/Entry.pm0000644000175000017500000002733610460673257014537 00000000000000package Lire::Report::Entry; use strict; use Carp; use Lire::Utils qw/ xml_encode check_object_param /; use Lire::Report::Group; =pod =head1 NAME Lire::Report::Entry - Interface to subreport's data. =head1 SYNOPSIS foreach my $name ( $entry->names() ) { print "Name: ", $name->{'content'}, "\n"; } foreach my $value ( $entry->values() ) { if ( ref $value eq 'Lire::Report::Group' ) { # Value is a group foreach my $e ( $value->entries() ) { print_entry( $e ); } } else { print "Value: ", $value->{'content'}, "\n"; } } =head1 DESCRIPTION The Lire::Report::Entry objects are used to hold the subreport's data. =head1 CONSTRUCTOR One creates a new Entry object by using the create_entry method on a Lire::Report::Subreport or Lire::Report::Group object. Use the add_name(), create_group() and add_value() methods to fill the entry. =cut sub new { my ( $class, $group ) = @_; check_object_param( $group, 'group', 'Lire::Report::Group' ); return bless( {'data' => [], 'group' => $group}, $class ); } =pod =head1 OBJECT METHODS =head2 row_idx() Returns the row index in the table body where this entry's data should be displayed. If undef, this entry shouldn't be displayed. =cut sub row_idx { $_[0]{'row_idx'} = $_[1] if @_ == 2; return $_[0]{'row_idx'}; } =pod =head2 subreport() Returns the Lire::Report::Subreport object in which this entry is contained. =cut sub subreport { my $self = $_[0]; my $parent = $self->group(); while ( $parent && $parent->parent_entry() ) { $parent = $parent->parent_entry()->group(); } return $parent; } =pod =head2 group() Returns the Lire::Report::Group object which contains this entry. =cut sub group { return $_[0]{'group'}; } =pod =head2 group_info() Returns the Lire::Report::GroupInfo which contains the information related to the group in which this entry is. =cut sub group_info { return $_[0]{'group'}->group_info(); } =pod =head2 data() Returns as an array the data contained in this entry. This is a list of hashes or Lire::Report::Group object. =cut sub data { return @{$_[0]->{'data'}}; } =pod =head2 data_by_name( $name ) Returns the data item contained in this Entry that was generated by the operator named $name. Returns undef if no such data item can be found. =cut sub data_by_name { my ( $self, $name ) = @_; foreach my $d ( @{$self->{'data'}} ) { if ( UNIVERSAL::isa( $d, 'Lire::Report::Group' ) ) { return $d if $d->group_info()->name() eq $name; } else { return $d if $d->{'col_info'}->name() eq $name; } } return undef; } =pod =head2 names() Returns the names of the entry. This is an array of hashes. The name's hash contains the following keys: =over 4 =item type Always set to 'name'. =item content That's the actual content of the name element. This contains the name in a format suitable for display. =item value This contains the unformatted value of the name. For example, when the name is a time string, this attribute will contains the time in seconds since epoch. =item missing_cases This value contains the number of DLF records which had a undefined value in one of the required fields to compute this statistic. =item range For some names, the actual content express a range (time, size, etc.). This attribute contains the length of the range. =item col_info The Lire::Report::ColumnInfo object describing this name. =back =cut sub names { return grep { $_->{'type'} eq 'name' } @{$_[0]->{'data'}}; } =pod =head2 add_name( $content, [$value], [$range] ) Adds a new name to this entry. Consult the documentation of the names() method for a description of the meaning of the various parameters which have the same meaning as the keys with the same name. The names, values and groups should be added in the order specified by this entry's GroupInfo. You'll get an exception otherwise. =cut sub add_name { my ( $self, $content, $value, $range ) = @_; $content = '' unless defined $content; $value = $content unless defined $value; my $idx = $#{$self->{'data'}} + 1; my $info = $self->group_info->info_by_index( $idx ); check_object_param( $info, "Data_$idx", 'Lire::Report::ColumnInfo' ); my %n = ('type' => 'name', 'content' => $content, 'value' => $value, 'col_info' => $info); $n{'range'} = $range if defined $range; push @{$self->{'data'}}, \%n; return; } =pod =head2 values() Returns the values of the entry. This is an array of hashes or objects. If the value is an hash, it has the following keys: =over 4 =item type Always set to 'value'. =item content That's the actual content of the value element. This contains the value in a format suitable for display. =item value This contains the unformatted value. For example, when bytes are displayed using "1M" or "1.1G", this will contain the value in single bytes. =item missing_cases The number of DLF records which had an undefined value in one of fields required by this operator. =item total This is used by values that represent an average. It contains the total which makes up the average. =item n This is used by values that represent an average. It contains the total which was used in the division to compute the average. =item col_info The Lire::Report::ColumnInfo object describing this value. =back =cut sub values { return grep { $_->{'type'} eq 'value' } @{$_[0]->{'data'}}; } =pod =head2 groups() Returns in an array the Lire::Report::Group contained in this Entry. =cut sub groups { return grep { UNIVERSAL::isa( $_, 'Lire::Report::Group' ) } @{$_[0]->{'data'}}; } =pod =head2 create_group() Creates a new group for this entry. This will also append it to this entry data. If you create the group out of order compared to the names and values that should go in that entry, you'll get an exception. =cut sub create_group { my $self = $_[0]; my $idx = $#{$self->{'data'}} + 1; my $info = $self->group_info->info_by_index( $idx ); check_object_param( $info, "Data_$idx", 'Lire::Report::GroupInfo' ); my $group = new Lire::Report::Group( $self, $info ); push @{$self->{'data'}}, $group; return $group; } =pod =head2 add_value( %value ) Adds a new value to this entry. The value hash should at least contains the 'content' key. It can also includes values for the 'n', 'total' and 'missing_cases' keys. Consult the documentation of the values() method for a description of the meaning of the various parameters: these have the same meaning as the keys with the same names. The names, values and groups should be added in the order specified by this entry's GroupInfo. You'll get an exception otherwise. =cut sub add_value { my $self = $_[0]; my $value = ref( $_[1] ) ? $_[1] : { @_[1..$#_] }; $value->{'content'} = "" unless defined $value->{'content'}; $value->{'value'} = $value->{'content'} unless defined $value->{'value'}; my $idx = $#{$self->{'data'}} + 1; my $info = $self->group_info()->info_by_index( $idx ); check_object_param( $info, "Data_$idx", 'Lire::Report::ColumnInfo' ); $value->{'type'} = 'value'; $value->{'col_info'} = $info; $value->{'n'} = undef unless exists $value->{'n'}; $value->{'total'} = undef unless exists $value->{'total'}; $value->{'missing_cases'} = 0 unless defined $value->{'missing_cases'}; push @{$self->{'data'}}, $value; return; } # # helper method for Lire::Report::Subreport::last_row_idx() # sub _last_row_idx { my $self = $_[0]; return undef unless defined $self->{'row_idx'}; my $last = $self->{'row_idx'}; foreach my $group ( $self->groups() ) { my $group_last = $group->_last_row_idx(); $last = $group_last if defined $group_last && $group_last > $last; } return $last; } # # helper method for Lire::Report::Subreport::getrow_by_idx() # sub _getrow_by_idx { my ( $self, $idx, $row ) = @_; if ( $self->{'row_idx'} == $idx ) { foreach my $item ( @{$self->{'data'}} ) { my @cells = ( UNIVERSAL::isa( $item, 'Lire::Report::Group' ) ? $item->summary_values() : $item ); foreach my $cell ( @cells ) { $row->[$cell->{'col_info'}->col_start()] = $cell; } } } else { foreach my $group ( $self->groups() ) { $group->_getrow_by_idx( $idx, $row ); } } } #------------------------------------------------------------------------ # Method write_report( $fh, $indent ) # sub write_report { my ( $self, $fh, $indent ) = @_; $fh ||= *STDOUT; my $pfx = ' ' x $indent; print $fh $pfx, "row_idx(); print $fh ">\n"; foreach my $d ( @{$self->{'data'}} ) { if ( $d->{'type'} eq 'name' ) { write_name( $fh, $pfx, $d ); } elsif ( $d->{'type'} eq 'value' ) { write_value( $fh, $pfx, $d ); } else { # Group $d->write_report( $fh, $indent + 1 ); } } print $fh "$pfx\n"; return; } #------------------------------------------------------------------------ # Function write_name( $fh, $pfx, $d ) # # Writes $d into a lire:name element. sub write_name { my ( $fh, $pfx, $d ) = @_; print $fh $pfx, ' {'value'} ne $d->{'content'}; print $fh qq! range="$d->{'range'}"! if defined $d->{'range'}; print $fh ">", xml_encode( $d->{'content'} ), "\n"; return; } #------------------------------------------------------------------------ # Function write_value($fh, $pfx, $d) # # Writes $d into a lire:value element. sub write_value { my ( $fh, $pfx, $d ) = @_; print $fh $pfx, ' {'total'}; print $fh qq! n="$d->{'n'}"! if defined $d->{'n'}; print $fh qq! value="$d->{'value'}"! if $d->{'value'} ne $d->{'content'}; print $fh ">$d->{'content'}\n"; return; } #------------------------------------------------------------------------ # Method delete() # # Remove circular references sub delete { my $self = $_[0]; foreach my $g ( grep { $_->{'type'} eq 'group' } $self->values() ) { $g->delete(); } %$self = (); return; } # keep perl happy 1; =pod =head1 SEE ALSO Lire::ReportParser::ReportBuilder(3pm) Lire::Report(3pm) Lire::Report::Subreport(3pm) Lire::Report::Section(3pm) Lire::Report::Group(3pm) =head1 VERSION $Id: Entry.pm,v 1.32 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/Report/TableInfo.pm0000644000175000017500000001661210460673257015274 00000000000000package Lire::Report::TableInfo; use strict; use base qw/ Lire::Report::GroupInfo /; use Lire::Config::Index; use Lire::Config::VariableIndex; use Carp; =pod =head1 NAME Lire::Report::TableInfo - Object that holds all the GroupInfo and ColumnInfo for one subreport =head1 SYNOPSIS my $info = $subreport->table_info; my $col_info = $info->colum_info( "request_total" ); =head1 DESCRIPTION The Lire::Report::TableInfo object holds the ColumnInfo and GroupInfo objects for one subreport.. =head1 CONSTRUCTOR =head2 new() Creates a new Lire::Report::TableInfo object. =cut sub new { my $self = bless( {'name' => "table", 'children' => [], 'row_idx' => 0, 'parent' => undef}, $_[0] ); $self->index( 0 ); return $self; } =pod =head2 column_info_by_name( $name ) Returns the Lire::Report::ColumnInfo object that has the name $name. Contrary to the method in Lire::Report::GroupInfo, this one will throw an exception if there is no column named $name. =cut sub column_info_by_name { my ( $self, $name ) = @_; my $col = $self->SUPER::column_info_by_name( $name ); croak "There is no column named $name" unless $col; return $col; } =pod =head2 column_info_by_col_start( $idx ) Returns the Lire::Report::ColumnInfo object that is starts at column index $idx. Contrary to the method in Lire::Report::GroupInfo, this one will throw an exception if this column is out of bounds. =cut sub column_info_by_col_start { my ( $self, $idx ) = @_; my $col = $self->SUPER::column_info_by_col_start( $idx ); croak "There is no column index $idx" unless $col; return $col; } =pod =head2 group_info( $name ) Returns the Lire::Report::GroupInfo object that has the name $name. Contrary to the method in Lire::Report::GroupInfo, this one will throw an exception if there is no column named $name. =cut sub group_info { my ( $self, $name ) = @_; # Cache the result of the base lookup unless ( exists $self->{'group_info'}{$name} ) { $self->{'group_info'}{$name} = $self->SUPER::group_info( $name ); } croak "There is no group named $name" unless $self->{'group_info'}{$name}; return $self->{'group_info'}{$name}; } =pod =head2 ncols() Returns the number of columns there is in this table. =cut sub ncols { my $self = $_[0]; my @cols = $self->column_infos(); return scalar @cols; } =pod =head2 column_infos() Returns an array containing all the columns of the table. Each element is a Lire::Report::ColumnInfo object. =cut sub column_infos { my $self = $_[0]; my @cols = $self->column_children(); my @groups = $self->group_children(); while ( @groups ) { my $g = shift @groups; push @cols, $g->column_children(); push @groups, $g->group_children(); } return sort { $a->col_start() <=> $b->col_start() } @cols; } =pod =head2 groups() Returns an array containing all the groups of the table. Each element is a Lire::Report::GroupInfo object. =cut sub groups { my $self = $_[0]; my @groups = ( $self ); my @children = ( $self ); while ( @children ) { my $g = shift @children; push @groups, $g->group_children(); push @children, $g->group_children(); } return @groups; } =pod =head2 columns_width() Returns an array where each element represents the suggested columns' width in characters. =cut sub columns_width { return map { $_->col_width() } $_[0]->columns(); } =pod =head2 header_rows() Returns an array reference containing one array reference for each rows in the header. Each row contains the ColumnInfo that should appear on the header line. The first row contains all the numerical columns and the categorical columns appear based on their nesting. The indices of the column is always equals to its column's start. =cut sub header_rows { my $self = $_[0]; my $rows = []; my @groups = $self->groups(); my @group_row; my $ncols = $self->ncols(); while ( @group_row = grep { $_->row_idx() == ( $#$rows + 1 ) } @groups ) { # Grab the ColumInfo in that row my @cols = (); foreach my $g ( @group_row ) { push @cols, grep { $_->class() eq 'categorical' } $g->column_children(); # Special case for the first row, all value columns go there push @cols, grep { $_->class eq 'numerical' } $self->column_infos() unless @$rows; } my $row = [ (undef) x $ncols ]; foreach my $col ( @cols ) { $row->[ $col->col_start() ] = $col; } push @$rows, $row; } return $rows; } =pod =head2 set_variables_indices() Registers this TableInfo's variables using Lire::Config::VariableIndex. =cut sub set_variables_indices { my $self = $_[0]; Lire::Config::Index->set_index( 'variables', new Lire::Config::VariableIndex( $self, 'both' ) ); Lire::Config::Index->set_index( 'categorical_variables', new Lire::Config::VariableIndex( $self, 'categorical' ) ); Lire::Config::Index->set_index( 'numerical_variables', new Lire::Config::VariableIndex( $self, 'numerical' ) ); return; } =pod =head2 reset_variable_indices() Removes the variables indices. This can be called to undo the effect of set_variables_indices(). =cut sub reset_variables_indices { my $self = $_[0]; Lire::Config::Index->set_index( 'variables', undef ); Lire::Config::Index->set_index( 'categorical_variables', undef ); Lire::Config::Index->set_index( 'numerical_variables', undef ); return; } # ------------------------------------------------------------------------ # Method compute_columns_width() # # Try to determine the width of all the columns sub compute_columns_width { my $self = $_[0]; $self->assign_columns_width; $self->correct_spanning_column_width( $self ); return; } #----------------------------------------------------------------------- # Methods write_report( $fh, $index ) sub write_report { my ( $self, $fh, $indent ) = @_; $fh ||= *STDOUT; my $pfx = ' ' x $indent; print $fh $pfx, qq{\n}; foreach my $i ( @{$self->{'children'}} ) { $i->write_report( $fh, $indent + 1 ); } print $fh $pfx, "\n"; return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Report::Subreport(3pm) Lire::Report::ColumnInfo(3pm) =head1 VERSION $Id: TableInfo.pm,v 1.26 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste =cut lire-2.1.1/all/lib/Lire/Report/Makefile.am0000644000175000017500000000302410077511266015113 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.7 2004/07/21 15:58:46 flacoste Exp $ ## Copyright (C) 2000-2001 Stichting LogReport Foundation LogReport@LogReport.org ## ## This file is part of Lire. ## ## Lire is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk allperllibdir = $(LR_PERL5LIBDIR)/Lire/Report allperllib_DATA = \ ChartConfig.pm \ ColumnInfo.pm \ Entry.pm \ Group.pm \ GroupInfo.pm \ Section.pm \ Subreport.pm \ TableInfo.pm man_MANS = \ ChartConfig.3pm \ ColumnInfo.3pm \ Entry.3pm \ Group.3pm \ GroupInfo.3pm \ Section.3pm \ Subreport.3pm \ TableInfo.3pm perlpackage = Lire::Report transform = s,^,$(perlpackage)::, EXTRA_DIST = $(allperllib_DATA) CLEANFILES = $(man_MANS) lire-2.1.1/all/lib/Lire/Report/Makefile.in0000644000175000017500000004334511677606132015142 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/include/rules.mk subdir = all/lib/Lire/Report ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(allperllib_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) transform = s,^,$(perlpackage)::, ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done allperllibdir = $(LR_PERL5LIBDIR)/Lire/Report allperllib_DATA = \ ChartConfig.pm \ ColumnInfo.pm \ Entry.pm \ Group.pm \ GroupInfo.pm \ Section.pm \ Subreport.pm \ TableInfo.pm man_MANS = \ ChartConfig.3pm \ ColumnInfo.3pm \ Entry.3pm \ Group.3pm \ GroupInfo.3pm \ Section.3pm \ Subreport.3pm \ TableInfo.3pm perlpackage = Lire::Report EXTRA_DIST = $(allperllib_DATA) CLEANFILES = $(man_MANS) all: all-am .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/Lire/Report/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/Lire/Report/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man3: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list=''; test -n "$(man3dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } install-allperllibDATA: $(allperllib_DATA) @$(NORMAL_INSTALL) test -z "$(allperllibdir)" || $(MKDIR_P) "$(DESTDIR)$(allperllibdir)" @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(allperllibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(allperllibdir)" || exit $$?; \ done uninstall-allperllibDATA: @$(NORMAL_UNINSTALL) @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(allperllibdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(allperllibdir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-allperllibDATA install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man3 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-allperllibDATA uninstall-man uninstall-man: uninstall-man3 .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ distclean distclean-generic distdir dvi dvi-am html html-am \ info info-am install install-allperllibDATA install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-man3 \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall \ uninstall-allperllibDATA uninstall-am uninstall-man \ uninstall-man3 .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lire-2.1.1/all/lib/Lire/Report/GroupInfo.pm0000644000175000017500000004265210460673257015344 00000000000000package Lire::Report::GroupInfo; use strict; use Carp; use POSIX qw/ ceil /; use Lire::DataTypes qw/ check_xml_name /; use Lire::Report::ColumnInfo; use Lire::Utils qw/ check_param check_object_param /; =pod =head1 NAME Lire::Report::GroupInfo - Object that groups columns created by the same aggregator. . =head1 SYNOPSIS my $info = $subreport->group_info( 0 ); print "Group's name: ", $info->name(), "\n"; print "Group's columns starts at: ", $info->index(), "\n"; =head1 DESCRIPTION The Lire::Report::GroupInfo object holds the ColumnInfo objects that were created by the same aggregator. =head1 CONSTRUCTOR =head2 new( $name ) You create a new Lire::Report::GroupInfo object by calling the create_group_info() method on one Lire::Report::TableInfo object or another Lire::Report::GroupInfo object. =cut sub new { my ( $class, $parent, $name ) = @_; check_param( $name, 'name', \&check_xml_name, "name isn't a valid XML name" ); check_object_param( $parent, 'parent', 'Lire::Report::GroupInfo' ); return bless( { 'name' => $name, 'children' => [], 'parent' => $parent }, $class ); } =pod =head1 OBJECT METHODS =pod =head2 name() Returns the name of this group. This name can be used to find the aggregator (from the report specification) that is responsible for the data held in this group. =cut sub name { return $_[0]{'name'}; } =pod =head2 row_idx() Returns the row index in which this group's categorical column's labels should be displayed in the table header. =cut sub row_idx { $_[0]{'row_idx'} = $_[1] if @_ == 2; return $_[0]{'row_idx'}; } =pod =head2 max_row_idx() =cut sub max_row_idx { my $self = $_[0]; my $max = $self->{'row_idx'}; foreach my $group ( $self->group_children() ) { my $idx = $group->max_row_idx(); $max = $idx if ( $idx > $max ); } return $max; } =pod =head2 parent_group_info() Returns the GroupInfo which contains this GroupInfo. This will be undef for the top-level TableInfo object. =cut sub parent_group_info { return $_[0]{'parent'}; } =pod =head2 index() Returns the column's index in the table at which the columns of this group starts. This will be undef until the group info object is added to a Lire::Subreport or another Lire::Group object. =cut sub index { my ( $self, $index ) = @_; if ( @_ == 2 ) { croak ( "can't modify starting column index once children were added" ) if $self->children; $self->{'index'} = $index; } return $self->{'index'}; } =pod =head2 children() Returns as an array, the Lire::Report::ColumnInfo and Lire::Report::GroupInfo objects contained in this group. =cut sub children { return @{$_[0]{'children'}}; } =pod =head2 info_by_index( $idx ) Returns the ColumnInfo or GroupInfo that is at index $idx among this GroupInfo children. =cut sub info_by_index { my ( $self, $idx ) = @_; croak( "info index out of bounds" ) if $idx > $#{$self->{'children'}}; return $self->{'children'}[$idx]; } =pod =head2 group_children Returns as an array, only the Lire::Report::GroupInfo contained in this GroupInfo. =cut sub group_children { return grep { $_->isa( 'Lire::Report::GroupInfo' ) } $_[0]->children; } =pod =head2 column_children Returns as an array, only the Lire::Report::ColumnInfo contained in this GroupInfo. =cut sub column_children { return grep { $_->isa( 'Lire::Report::ColumnInfo' ) } $_[0]->children(); } =pod =head2 categorical_names() Returns the categorical columns' names as an array ref. =cut sub categorical_names { my $self = $_[0]; my @names = (); foreach my $col ( $self->column_children() ) { push @names, $col->name() if $col->class() eq 'categorical'; } return \@names; } =pod =head2 create_column_info( $name, $class, $type, [$label]]) Creates a new Lire::Report::ColumnInfo object as a child of this GroupInfo. The column info attributes are initialized based on $name, $class, $type and $label. This will set the index of the ColumnInfo object. Returns the created ColumnInfo object. =cut sub create_column_info { my ( $self, $name, $class, $type, $label ) = @_; my $info = new Lire::Report::ColumnInfo( $self, $name, $class, $type, $label ); my $index = $self->next_column_index(); $info->index( $index ); push @{$self->{'children'}}, $info; return $info; } =pod =head2 create_group_info( $name ) Create a Lire::Report::GroupInfo which as a child of this group. This will also set the starting column index on the GroupInfo object. The $name parameter should contain the name of the report specification aggregator that is responsible for the content of this group. Returns the created GroupInfo object. =cut sub create_group_info { my ( $self, $name ) = @_; check_param( $name, 'name', \&check_xml_name, "name isn't a valid XML name" ); my $info = new Lire::Report::GroupInfo( $self, $name ); my $index = $self->next_column_index(); $info->index( $index ); $info->row_idx( $self->row_idx + 1 ); push @{$self->{'children'}}, $info; return $info; } #------------------------------------------------------------------------ # Methods next_column_index() # # Returns the next column's index that should be used when a ColumnInfo or # GroupInfo object is added. sub next_column_index { my $self = $_[0]; croak ( "next_column_index: starting column index wasn't set" ) unless defined $self->{'index'}; return $self->index() unless ( @{$self->{'children'}} ); my $last = $self->{'children'}[$#{$self->{'children'}}]; return ( UNIVERSAL::isa( $last, "Lire::Report::GroupInfo" ) ? $last->next_column_index() : $last->index() + 1 ); } =pod =head2 column_info_by_name( $name ) Returns the Lire::Report::ColumnInfo object that has the name $name. This method searches in the current group as well as in its subgroups. Returns undef if the column isn't found. =cut sub column_info_by_name { my ( $self, $name ) = @_; # Look first into our immediate children my ( $col ) = grep { $_->name() eq $name } $self->column_children(); return $col if $col; # Look into subgroups foreach my $g ( $self->group_children() ) { my $c = $g->column_info_by_name( $name ); return $c if $c; } return; } =pod =head2 column_info_by_col_start( $col_idx ) Returns the Lire::Report::ColumnInfo object that starts in column index $col_idx. This method searches in the current group as well as in its subgroups. Returns undef if the column isn't found in the current group. =cut sub column_info_by_col_start { my ( $self, $idx ) = @_; # Look first into our immediate children my ( $col ) = grep { $_->col_start == $idx } $self->column_children(); return $col if $col; # Look into subgroups foreach my $g ( $self->group_children() ) { $col = $g->column_info_by_col_start( $idx ); return $col if $col; } return; } =pod =head2 group_info( $name ) Returns the Lire::Report::GroupInfo object that has the name $name. This will be undef if it cannot be found in this group info. =cut sub group_info { my ( $self, $name ) = @_; # Look first into our immediate children my ( $group ) = grep { $_->name() eq $name } $self->group_children(); # Look into subgroups foreach my $g ( $self->group_children() ) { $group = $g->group_info( $name ); return $group if $group; } return; } # ------------------------------------------------------------------------ # Method compute_group_layout( [$col_start]) # # Calculates the col-start, col-end attributes of each of this # group column-info. # # $col_start is the column at which the group should start assigning. # Defaults to 0. # # Returns the column number that should be assigned next. # # The algorithm for the table layout is to assign all the categorical # columns first. Rationale being this is that only those columns use # spanning to show the grouping indentation. To achieve this, we also # process the categorical columns of the first subgroup recursively. # # After that, the numerical columns (and recursively the first # subgroup's numerical columns are assigned and the other groups are # processed in order as if they were independant subtables (possibly # also involving grouping # # For example, this XML report : # # Cat1 # Cat2 # Num1 # # # G1Cat1 # G1Num1 # # # # # G2Cat1 # # # G3Cat1 # G3Cat2 # G3num1 # # # # # # # would be rendered as : # # +-+--------+------+-----+-------+--+--------+------+---------+ # |Cat1 |Cat2 | Num1| | | | # +-+--------+------+ + +--+--------+------+ | # | |G1Cat1 | | G1Num1|G2Cat1 | | # +-+--------+------+ + +--+--------+------+ | # | | | | |G3Cat1 |G3Cat2| G3Num1| # +-+--------+------+-----+-------+--+--------+------+---------+ sub compute_group_layout { my ( $self, $col_start ) = @_; $col_start = 0 unless defined $col_start; # -1 because col_start is a 0-based index my $cat_col_end = $col_start + $self->count_categorical_columns - 1; # Assign the categorical columns $self->assign_categorical_columns( $col_start, $cat_col_end ); # Process the other columns $self->assign_numerical_columns( $cat_col_end + 1 ); return; } # ------------------------------------------------------------------------ # Method assign_categorical_columns( $col_start, $cat_col_end ) # # Calculates the col-start, col-end attributes of each for this group's # categorical columns. # # $col_start is the column at which the group should start assigning # $cat_col_end is the last column which can be used for categorical data # sub assign_categorical_columns { my ( $self, $col_start, $cat_col_end ) = @_; # The categorical columns in this group to process my @cat_columns = grep { $_->class() eq 'categorical' } $self->column_children(); # The number of available categorical columns not assigned my $cat_column_avail = $cat_col_end - $col_start + 1; die "ASSERTION FAILED: this group has ", scalar @cat_columns, " categorical columns but only $cat_column_avail are available" if $cat_column_avail < @cat_columns; my $col_no = $col_start; while ( my $col = shift @cat_columns ) { # + 1 since $col isn't in @cat_columns my $span = ceil( $cat_column_avail / (@cat_columns + 1) ); $col->col_start( $col_no ); die "ASSERTION FAILED: span outside of the columns assigned to categorical data" if $col_no + $span -1 > $cat_col_end; $col->col_end( $col_no + $span - 1 ); $col_no += $span; $cat_column_avail -= $span; } # Assign the categorical columns of the first group my ($first_group) = $self->group_children(); $first_group->assign_categorical_columns( $col_start + 1, $cat_col_end ) if defined $first_group; return; } # ------------------------------------------------------------------------ # Method count_columns # # Returns the number of columns in this group and its subgroups sub count_columns { my $self = $_[0]; my $count = $self->column_children(); foreach my $group ( $self->group_children() ) { $count += $group->count_columns(); } return $count; } # ------------------------------------------------------------------------ # Method count_categorical_columns # # Returns the number of categorical columns present in this # group. This includes the categorical columns of the first subgroups. # sub count_categorical_columns { my ($self) = @_; my $count = grep { $_->class() eq 'categorical' } $self->column_children(); my @groups = $self->group_children(); $count += $groups[0]->count_categorical_columns() if @groups; return $count; } # ------------------------------------------------------------------------ # Method assign_numerical_columns( $col_start ) # # Assigns the numerical columns of this group # # $col_start is the column number at which the assignment should # start # # Returns the next column number to assign. sub assign_numerical_columns { my ( $self, $col_start ) = @_; my $col_no = $col_start; my $group_processed = 0; foreach my $child ( $self->children() ) { if ( $child->isa( 'Lire::Report::ColumnInfo' ) ) { # Already assigned next if $child->class() eq 'categorical'; # Numerical column are always 1 in width $child->col_start( $col_no ); $child->col_end( $col_no ); $col_no++; } else { # This child is a GroupInfo if ( $group_processed ) { # If its not the first one, we have to assign both its # categorical and numerical columns. $col_no = $child->compute_group_layout( $col_no ); } else { # If this is the first GroupInfo, we assign its numerical # colum. $col_no = $child->assign_numerical_columns( $col_no ); $group_processed++; } } } return $col_no; } # ------------------------------------------------------------------------ # Method assign_columns_width() # # Sets the width of each column based on columns which only uses one # cell. The width is set to the max-chars value. If the column spans # more than one cell, its width is set to 2, since this column is used # as indentation for grouping purpose (consult the example in # compute_group_layout). sub assign_columns_width { my $self = $_[0]; foreach my $col ( $self->column_children() ) { $col->col_width( $col->col_start() == $col->col_end() ? $col->max_chars() : 2 ); } foreach my $group ( $self->group_children() ) { $group->assign_columns_width(); } return; } # ------------------------------------------------------------------------ # Method correct_spanning_column_width( $table_info) # # Make sure that the sum of the width spanned by spanning columns is # enough to hold their value. # # $table_info is a reference to the TableInfo object which contains the # all columns sub correct_spanning_column_width { my ( $self, $table_info ) = @_; foreach my $col ( $self->column_children() ) { my $start = $col->col_start(); my $end = $col->col_end(); next unless $start != $end; # Check the width of the span my $width = 0; foreach ( my $i = $start; $i <= $end; $i++ ) { $width += $table_info->column_info_by_col_start( $i )->col_width(); } next if $col->max_chars <= $width; # This column is bigger than the span, increase proportionally # the columns width, except the first one which is used # for indentation. # (We don't need to subtract one, since we need a column count # and not a column index) my $extra = ceil( ($col->max_chars - $width) / ( $end - $start) ); foreach ( my $i = $start + 1; $i <= $end; $i++ ) { my $col = $table_info->column_info_by_col_start( $i ); $col->col_width( $col->col_width + $extra ); } } foreach my $group ( $self->group_children() ) { $group->correct_spanning_column_width( $table_info ); } return; } #----------------------------------------------------------------------- # Methods write_report( $fh, $index ) sub write_report { my ( $self, $fh, $indent ) = @_; $fh ||= *STDOUT; my $pfx = ' ' x $indent; print $fh $pfx, qq{\n}; foreach my $i ( $self->children() ) { $i->write_report( $fh, $indent + 1 ); } print $fh $pfx, "\n"; } #------------------------------------------------------------------------ # Method delete() # # Remove circular references sub delete { my $self = $_[0]; foreach my $c ( $self->children() ) { $c->delete(); } %$self = (); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Report::Subreport(3pm) Lire::Report::ColumnInfo(3pm) =head1 VERSION $Id: GroupInfo.pm,v 1.22 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut lire-2.1.1/all/lib/Lire/ReportParser.pm0000644000175000017500000006424410460673255014610 00000000000000package Lire::ReportParser; use strict; use base qw/ Lire::DocBookParser Lire::Config::Parser /; use Lire::Report::TableInfo; use Lire::Config::ListSpec; use Lire::Config::ChartSpec; =pod =head1 NAME Lire::ReportParser - Lire::XMLParser which parses XML reports =head1 SYNOPSIS package MyParser; use base qw/ Lire::ReportParser /; sub parse_end { return "Finished"; } package main:: my $parser = new MyParser; my $result = eval { $parser->parsefile( "report.xml" ) }; croak "Error parsing report.xml: $@" if $@ print $result, "\n"; =head1 DESCRIPTION This is a Lire::XMLParser(3pm) subclass which handle XML document adhering to the Lire Report Markup Language format. It's primary purpose is to write custom handlers for the Lire XML Report format. =head1 USAGE You create an instance of a subclass of Lire::ReportParser and use either one of the parse() or parsefile() methods to process the XML reports. You'll probably never use the Lire::ReportParser module directly; you'll likely use one subclass which actually does something when processing the document. =head2 new( %args ) my $parser = new Lire::ReportParser::ReportBuilder(); The new() method takes parameters in the form of 'key' => value pairs. The available parameters are specific to each processor. There are no generic parameters. =cut sub namespaces { my $self = $_[0]; return { %{$self->Lire::Config::Parser::namespaces()}, 'http://www.logreport.org/LRML/' => 'lire' }; } sub elements_spec { my $self = $_[0]; return { %{$self->Lire::Config::Parser::elements_spec()}, %{$self->Lire::DocBookParser::elements_spec()}, 'lire:report' => [ 'lire:title', 'lire:date', 'lire:timespan', 'lire:description', 'lire:section' ], 'lire:section' => [ 'lire:title', 'lire:description', 'lire:subreport', 'lire:missing-subreport' ], 'lire:subreport' => [ 'lire:title', 'lire:description', 'lire:chart-configs', 'lire:table' ], 'lire:missing-subreport' => [], 'lire:title' => [ 'PCDATA' ], 'lire:description' => [ @Lire::DocBookParser::top_levels ], 'lire:date' => [ 'PCDATA' ], 'lire:timespan' => [ 'PCDATA' ], 'lire:table' => [ 'lire:table-info', 'lire:group-summary', 'lire:entry' ], 'lire:entry' => [ 'lire:name', 'lire:value', 'lire:group' ], 'lire:name' => [ 'PCDATA' ], 'lire:value' => [ 'PCDATA' ], 'lire:group' => [ 'lire:group-summary', 'lire:entry' ], 'lire:chart-configs' => [ 'lrcml:param' ], 'lire:table-info' => [ 'lire:column-info', 'lire:group-info' ], 'lire:group-info' => [ 'lire:column-info', 'lire:group-info' ], 'lire:column-info' => [], 'lire:group-summary' => [ 'lire:value' ], } } =pod =head1 WRITING AN XML REPORT PROCESSOR Using Lire::ReportParser, one can write an XML report processor. The programming model is similar to the expat event-based interface or the well-known SAX model. The principal difference with those models is that this module offers hooks specifically tailored for Lire's XML reports. For example, instead of having one generic element-start event, you have methods for each specific type of element, making it easy to hook on only the elements you're interested in. It also offers some functions that make it easy to determine the context (always a difficulty in event-based programming). If you are uncomfortable with that kind of programming, there is also an object-oriented API available to the XML reports. That API is more similar to DOM type of programming. Its principal drawback is that its less performant since it has to parse the whole XML document in memory to build an object representation. But if you need to "navigate" the document, it's a lot better than the event-based API. The main way of using that API to write a custom XML report handler is by subclassing the Lire::ReportParser module and overriding the functions related to the elements you are interested in. There are 3 categories of methods you can override. =over 4 =item Customization Methods Those are methods that customize the way the Lire::ReportParser will operate. The most important one is the new() "constructor". =item Generic element methods Those are methods that are invoked on each element before the more specific or higher ones and can be used to hook before the other events are synthesized. =head1 HIGH-LEVEL EVENT METHODS For each element defined, an I_start() and an I_end() method are invoked. For elements that contains character data, an I_char() method will also be invoked altough, you probably want to hook onto the easier handle_I() methods in these cases. When you override any of those mehod (except the handle_I() one), you B invoke the parent method also: sub subreport_start { my ( $self, $name, $attr ) = @_; $self->SUPER::subreport_start( $name, $attr ); # Processor specific handling. } =head2 report_start( $name, $attr ) Called when the report element start tag is encountered. The only defined attribute is C. The current version is 2.0, but older 1.0 report can still be parsed. =cut sub report_start { my ( $self, $name, $attr ) = @_; $self->init_stack( 'config_spec' ); $self->init_stack( 'config_value' ); $self->error( "missing 'version' attribute on root element\n" ) unless defined $attr->{'version'}; $self->error( "'version' attribute should be 2.0 or 2.1: $attr->{'version'}") unless $attr->{'version'} eq '2.0' || $attr->{'version'} eq '2.1'; $self->{'lrp_subreport_count'} = 0; return; } =pod =head2 report_end( $name ) Called when the report element end tag is encountered. =cut sub report_end { } sub title_start { my ( $self, $name, $attr ) = @_; $self->collector_start( $name ); return; } sub title_char { my ( $self, $char ) = @_; $self->collector_char( $char ); return; } sub title_end { my ( $self, $name ) = @_; my $title = $self->get_collector( $name ); $title =~ s/\s+/ /g; $self->handle_title( $title ); return; } =pod =head2 handle_title( $title ) Method invoked after the C element was processed. The $title parameter contains the content of the element. This can be a report's, subreport's or section's title. You'll need to use the in_element() method to determine the context. =cut sub handle_title { my ( $self, $title ) = @_; return; } =pod =head2 handle_description( $docbook_desc ) Unless the description_start and description_end events are overriden the content of the description will be collected and will be available in the handle_description() method. =cut sub description_start { my $self = $_[0]; $self->dbk_init(); return; } sub description_end { my $self = $_[0]; $self->handle_description( $self->dbk_string() ); return; } sub date_start { my ( $self, $name, $attr ) = @_; $self->{'lrp_curr_date'} = { 'date' => '', 'time' => $attr->{'time'} }; return; } sub date_char { $_[0]->{'lrp_curr_date'}{'date'} .= $_[1]; return; } sub date_end { my ( $self, $name ) = $_[0]; $self->handle_date( $self->{'lrp_curr_date'}{'date'}, $self->{'lrp_curr_date'}{'time'} ); return; } =pod =head2 handle_date( $date, $date_epoch ) Called after the C<date> element was parsed. The formatted date is available in the $date parameter, the date in number of seconds since the epoch is available in the $date_epoch parameter. This can be the report's or a subreport's date, you'll need to use the in_element() method to determine the appropriate context. =cut sub handle_date {} sub timespan_start { my ( $self, $name, $attr ) = @_; $self->{'lrp_curr_timespan'} = { 'timespan' => '', 'start' => $attr->{'start'}, 'end' => $attr->{'end'}, 'period' => $attr->{'period'} }; return; } sub timespan_char { my ( $self, $char ) = @_; $self->{'lrp_curr_timespan'}{'timespan'} .= $char; return; } sub timespan_end { my ( $self) = @_; $self->handle_timespan( $self->{'lrp_curr_timespan'}{'timespan'}, $self->{'lrp_curr_timespan'}{'start'}, $self->{'lrp_curr_timespan'}{'end'}, $self->{'lrp_curr_timespan'}{'period'} ); return; } =pod =head2 handle_timespan( $timespan, $epoch_start, $epoch_end, $period ) Called after the C<timespan> element was parsed. The formatted timespan is available in the $timespan parameter, starting and ending dates of the timespan are available as number of seconds since the epoch in the $epoch_start and $epoch_end parameters. The $period parameter contians the timespan's period attribute. This can be the timespan of the report or the subreport, you'll need to use the in_element() method to determine the appropriate context. =cut sub handle_timespan {} =pod =head2 section_start( $name, $attr ) Called when the opening tag of a C<section> element is encountered. =cut sub section_start { my ( $self, $name, $attr ) = @_; $self->{'lrp_section_subreport_count'} = 0; return; } =pod =head2 section_end( $name ) Called when the closing tag of a C<section> element is encountered. =cut sub section_end { my $self = $_[0]; $self->{'lrp_section_subreport_count'} = 0; return; } =pod =head2 missing_subreport_start( $name, $attr ) Called when the opening tag of a C<missing-subreport> element is encountered. The C<superservice> attribute contains the superservice's of the subreport, the C<type> attribute contains the report specification ID and the C<reason> attribute will contains the reason why the subreport is missing. =cut sub missing_subreport_start {} =pod =head2 missing_subreport_end( $name ) Called when the closing tag of a C<missing-subreport> element is encountered. =cut sub missing_subreport_end {} =pod =head2 subreport_start( $name, $attr ) Called when the opening tag of the C<subreport> element is encountered. The C<superservice> attribute contains the subreport's superservice and the C<type> attribute contains the ID of the report specification that was used to generate that subreport. =cut sub subreport_start { my ( $self, $name, $attr ) = @_; $self->error( "missing 'superservice' attribute" ) unless defined $attr->{'superservice'}; $self->error( "missing 'type' attribute" ) unless defined $attr->{'type'}; $self->{'lrp_section_subreport_count'}++; $self->init_stack( 'lrp_group' ); $self->init_stack( 'lrp_entry' ); $self->{'lrp_subreport'} = $attr; return; } =pod =head2 subreport_end( $name ) Called when the C<subreport>'s closing tag is encountered. =cut sub subreport_end { my $self = $_[0]; $self->error( "ASSERTION failed: 'lrp_group' stack should be empty\n" ) unless $self->is_stack_empty( 'lrp_group' ); $self->error( "ASSERTION failed: 'lrp_group' stack should be empty\n" ) unless $self->is_stack_empty( 'lrp_entry' ); delete $self->{'lrp_subreport'}; $self->{'lrp_curr_table_info'} = undef; $self->{'lrp_curr_group_info'} = undef; $self->{'lrp_subreport_count'}++; return; } =pod =head2 table_start( $name, $attr ) Called when the opening tag of the C<table> element is encountered. The C<show> attribute contains the maximum number of entries that should be displayed (there may more entries than this number). =cut sub table_start { my ( $self, $name, $attr ) = @_; $self->stack_push( 'lrp_group', { 'entry_count' => 0, 'show' => $attr->{'show'}, } ); $self->{'lrp_curr_table'} = $self->stack_peek( 'lrp_group' ); return; } =pod =head2 table_end( $name ) Called when the C<table>'s closing tag is encountered. =cut sub table_end { my $self = $_[0]; $self->stack_pop( 'lrp_group' ); delete $self->{'lrp_curr_table'}; return; } =pod =head2 table_info_start( $name, $attr ) Called when the C<table-info>'s closing tag is encountered. There should be no reason for subclasses to override this method. The Lire::ReportParser takes care of parsing the C<table-info> content and offers that information through a Lire::Report::TableInfo object which is accessible through the current_table_info() method. =cut sub table_info_start { my ( $self, $name, $attr ) = @_; $self->{'lrp_curr_table_info'} = new Lire::Report::TableInfo(); $self->init_stack( 'lrp_group-info' ); $self->stack_push( 'lrp_group-info', $self->{'lrp_curr_table_info'} ); return; } =pod =head2 table_info_end( $name ) Called when the C<table-info>'s closing tag is encountered. See table_info_start() documentation for important comments. =cut sub table_info_end { my $self = $_[0]; $self->stack_pop( 'lrp_group-info' ); $self->stack_peek( 'lrp_group' )->{'group_info'} = $self->current_table_info(); $self->error( "ASSERTION failed: stack 'lrp_group-info' should be empty" ) unless $self->is_stack_empty( 'lrp_group-info' ); return; } =pod =head2 group_info_start( $name, $attr ) Called when the C<group-info>'s opening tag is encountered. See table_info_start() documentation for important comments. =cut sub group_info_start { my ( $self, $name, $attr ) = @_; my $curr_info = $self->stack_peek( 'lrp_group-info' ); $self->stack_push( 'lrp_group-info', $curr_info->create_group_info( $attr->{'name'} ) ); return; } =pod =head2 group_info_end( $name ) Called when the C<group-info>'s closing tag is encountered. See table_info_start() documentation for important comments. =cut sub group_info_end { my $self = $_[0]; $self->stack_pop( 'lrp_group-info' ); return; } =pod =head2 column_info_start( $name, $attr ) Called when the C<column-info>'s opening tag is encountered. See table_info_start() documentation for important comments. =cut sub column_info_start { my ( $self, $name, $attr ) = @_; my $group_info = $self->stack_peek( 'lrp_group-info' ); my $info = $group_info->create_column_info( $attr->{'name'}, $attr->{'class'}, $attr->{'type'}, $attr->{'label'} ); $info->max_chars( $attr->{'max-chars'} ); $info->avg_chars( $attr->{'avg-chars'} ); $info->col_start( $attr->{'col-start'} ); $info->col_end( $attr->{'col-end'} ); $info->col_width( $attr->{'col-width'} ); return; } =pod =head2 column_info_end( $name ) Called when the C<column-info>'s closing tag is encountered. See table_info_start() documentation for important comments. =cut sub column_info_end {} =pod =head2 group_summary_start( $name, $attr ) Called when the C<group-summary>'s opening tag is encountered. =cut sub group_summary_start { my ( $self, $name, $attr ) = @_; return; } =pod =head2 group_summary_end( $name ) Called when the C<group-summary>'s closing tag is encountered. =cut sub group_summary_end { my $self = $_[0]; return; } =pod =head2 group_start( $name, $attr ) Called when the opening tag of the C<group> element is encountered. C<group> elements introduce a kind of nested table. The C<show> attribute contains the maximum number of entries that should be displayed, altough more entries may be present in the report. =cut sub group_start { my ( $self, $name, $attr ) = @_; my $entry = $self->stack_peek( 'lrp_entry' ); $entry->{'child_idx'}++; my $info = $entry->{'group_info'}->info_by_index( $entry->{'child_idx'} ); $self->stack_push( 'lrp_group', { 'entry_count' => 0, 'show' => $attr->{'show'}, 'group_info' => $info, } ); return; } =pod =head2 group_end( $name ) Called when the C<group>'s closing tag is encountered. =cut sub group_end { my $self = $_[0]; $self->stack_pop( 'lrp_group' ); return; } =pod =head2 entry_start( $name, $attr ) Called when the opening tag of an C<entry> element is encountered. =cut sub entry_start { my ( $self, $name, $attr ) = @_; my $group = $self->stack_peek( 'lrp_group' ); $group->{'entry_count'}++; $self->stack_push( 'lrp_entry', { %$attr, 'child_idx' => -1, 'group_info' => $group->{'group_info'}, } ); return; } =pod =head2 entry_end( $name ) Called when the C<entry>'s closing tag is encountered. =cut sub entry_end { my $self = $_[0]; $self->stack_pop( 'lrp_entry' ); return; } sub name_start { my ( $self, $name, $attr ) = @_; my $entry = $self->stack_peek( 'lrp_entry' ); $entry->{'child_idx'}++; my $info = ( $attr->{'col'} ? $self->current_table_info()->column_info_by_name( $attr->{'col'} ) : $entry->{'group_info'}->info_by_index( $entry->{'child_idx'} ) ); $self->{'lrp_curr_name'} = { %$attr, 'content' => "", 'col_info' => $info, }; return; } sub name_char { my ( $self, $char ) = @_; $self->{'lrp_curr_name'}{'content'} .= $char; return; } sub name_end { my $self = $_[0]; $self->{'lrp_curr_name'}{'value'} = $self->{'lrp_curr_name'}{'content'} unless defined $self->{'lrp_curr_name'}{'value'}; $self->handle_name( $self->{'lrp_curr_name'} ); return; } =pod =head2 handle_name( $name_rec ) Called after a C<name> element was parsed. The $name_rec parameter is an hash reference which contains the different values of the name datum. Keys that are defined in this hash: =over 4 =item content That's the actual content of the name element. This contains the name in a format suitable for display. =item value This contains the unformatted value of the name. For example, when the name is a time string, this attribute will contains the time in seconds since epoch. =item range For some names, the actual content express a range (time, size, etc.). This attribute contains the length of the range. =item col_info The Lire::ColumnInfo object describing the column in which this name appears. =back =cut sub handle_name {} sub value_start { my ( $self, $name, $attr ) = @_; # Value in group-summary are handled differently because # they aren't part of the entry children. $self->stack_peek( 'lrp_entry' )->{'child_idx'}++ unless $self->within_element( "lire:group-summary" ); $self->{'lrp_curr_value'} = { %$attr, 'content' => "", 'col_info' => $self->current_table_info()->column_info_by_name( $attr->{'col'} ), }; return; } sub value_char { my ( $self, $char ) = @_; $self->{'lrp_curr_value'}{'content'} .= $char; return; } sub value_end { my $self = $_[0]; $self->{'lrp_curr_value'}{'value'} = $self->{'lrp_curr_value'}{'content'} unless defined $self->{'lrp_curr_value'}{'value'}; if ( $self->within_element( "lire:group-summary" ) ) { $self->handle_summary_value( $self->{'lrp_curr_value'} ); } else { $self->handle_value( $self->{'lrp_curr_value'} ); } return; } =pod =head2 handle_value( $value_rec ) Called after a C<value> element was parsed. The $value_rec parameter is an hash reference which contains the different values of the value datum. Keys that are defined in this hash: =over 4 =item content That's the actual content of the value element. This contains the value in a format suitable for display. =item value This contains the unformatted value. For example, when bytes are displayed using "1M" or "1.1G", this will contains the value in bytes. =item total This is used by values that represent an average. It contains the total which makes up the average. =item n This is used by values that represent an average. It contains the total which was used in the division to compute the average. =item col_info The Lire::ColumnInfo object describing the column in which this name appears. =back =cut sub handle_value {} =pod =head2 handle_summary_value( $value_rec ) Called after a C<value> element located in the group-summary element was parsed. The $value_rec parameter is identical than in the handle_value() method. =cut sub handle_summary_value {} sub chart_configs_start { my $self = $_[0]; my $spec = new Lire::Config::ListSpec( 'name' => 'chart_configs' ); $spec->add( new Lire::Config::ChartSpec( 'name' => 'chart' ) ); $self->stack_push( 'config_spec', $spec ); $self->stack_push( 'config_value', $spec->instance() ); return; } sub chart_configs_end { my $self = $_[0]; $self->stack_pop( 'config_spec' ); $self->handle_chart_configs( $self->stack_pop( 'config_value' )->as_value() ); return; } =pod =head2 handle_chart_configs( $configs ) If the Subreport contained chart configurations, an array reference of Lire::Report::ChartConfig objects will be passed to this event handler. =cut sub handle_chart_configs { my ( $self, $configs ) = @_; return; } =pod =head1 CONTEXT METHODS Finally, here a bunch of additional methods that can be used to query some context information when processing elements. =cut =pod =head2 current_subreport_count( ) Returns the number of subreport that are present to date in the report. That number is equals to the number of processed C<subreport> elements, i.e. the current subreport isn't counted untill the closing tag was processed. =cut sub current_subreport_count { return $_[0]{'lrp_subreport_count'}; } =pod =head2 current_section_subreport_count( ) Returns the number of subreport that are present to date in the section. That number is equals to the number of processed C<subreport> elements, i.e. the current subreport isn't counted untill the closing tag was processed. =cut sub current_section_subreport_count { return $_[0]{'lrp_section_subreport_count'}; } =pod =head2 current_date( ) Returns the content of the C<date> element that applies to the current element. This will either be the current subreport's date or the default one taken from the C<report> element. The date is returned as an hash reference which will contain the formatted date in the C<date> key and the date in seconds since epoch in the C<time> key. =cut sub current_date { return $_[0]{'lrp_curr_date'}; } =pod =head2 current_timespan( ) Returns the content of the C<timespan> element that applies to the current element. This will either be the current subreport's date or the default one taken from the C<report> element. The timespan is returned as an hash reference which will contain the formatted timespan in the C<timespan> key. The starting and ending date of the timespan are available as seconds since epoch in the C<start> and C<end> keys. The C<period> key contains the report's timespan. =cut sub current_timespan { return $_[0]{'lrp_curr_timespan'}; } =pod =head2 current_superservice( ) Useful in C<subreport> context, it returns the superservice's of the current subreport. =cut sub current_superservice { return $_[0]{'lrp_subreport'}{'superservice'}; } =pod =head2 current_type( ) Useful in C<subreport> context, it returns the ID of the report specification that was used to generate the current subreport. =cut sub current_type { return $_[0]{'lrp_subreport'}{'type'}; } =pod =head2 current_table_info() Useful when processing C<group> and C<entry>, this returns a Lire::Report;:TableInfo object which describes the layout of the current table. =cut sub current_table_info { return $_[0]{'lrp_curr_table_info'}; } =pod =head2 current_group_entry_show( ) Useful in C<table> and C<group> context, it returns the maximum number of entries that should be displayed. =cut sub current_group_entry_show { return $_[0]->stack_peek( 'lrp_group' )->{'show'}; } =pod =head2 show_current_entry( ) Useful in C<entry> context , this can be used to test whether or not the current C<entry> should be displayed based on the current entry index and the parent's C<show> attribute. =cut sub show_current_entry { my $group = $_[0]->stack_peek( 'lrp_group' ); return ( !defined $group->{'show'} || $group->{'entry_count'} <= $group->{'show'} ); } =pod =head2 current_table_entry_count( ) Useful in C<table> context, it returns the number of entries that were processed so far. This only reports the entries in the C<table> element, not counting the one in the nested C<group>. =cut sub current_table_entry_count { return $_[0]{'lrp_curr_table'}{'entry_count'}; } 1; __END__ =pod =head1 SEE ALSO Lire::Report(3pm), Lire::XMLParser(3pm) Lire::ReportParser::AsciiDocBookFormatter(3pm), Lire::ReportParser::AsciiWriter(3pm), Lire::ReportParser::HTMLDocBookFormatter(3pm), Lire::ReportParser::HTMLWriter(3pm), Lire::ReportParser::ReportBuilder(3pm), Lire::ReportParser::ExcelWriter(3pm), Lire::Report::TableInfo(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: ReportParser.pm,v 1.52 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Sum.pm����������������������������������������������������������������������0000644�0001750�0001750�00000013256�10765035043�012714� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Sum; use strict; use base qw/ Lire::SimpleStat /; use Carp; use Lire::DataTypes qw/ is_numeric_type format_numeric_type/; use Lire::Utils qw/ ratio100 sql_quote_name /; =pod =head1 NAME Lire::Sum - Lire class that implements the sum operator =head1 SYNOPSIS use Lire::Sum =head1 DESCRIPTION Class that implements the sum operator. This operator will compute the field's sum in a group of DLF records. It's possible to compute a weighted sum in which each value is first multiplied by the value of another DLF field. Its also possible to express the count as a ratio of the total count for the group or table. =head1 METHODS =head2 new( %params ) Creates a new Lire::Count object. In addition to the values supported by its parents, the weight and ratio attributes will be initialized to the values specified in the %params argument. =cut sub new { my $proto = shift; my $class = ref $proto || $proto; my $self = bless { 'ratio' => 'none', }, $class; $self->init( @_, 'op' => "sum" ); my %args = @_; $self->weight( $args{'weight'} ) if exists $args{'weight'}; $self->ratio( $args{'ratio'} ) if exists $args{'ratio'}; return $self; } =pod =head2 weight( [$new_weight] ) Returns the DLF field's name by which the values will be multiplied before being summed. You can change the weight field by specifying a new name as the $new_weight parameter. Use undef to remove the use of a weighting field. =cut sub weight { my ( $self, $weight ) = @_; if ( @_ == 2 ) { if ( defined $weight ) { croak "'$weight' isn't a defined field in the specification's schema" unless $self->report_spec()->has_field( $weight ); croak "$weight isn't a numeric type", unless is_numeric_type( $self->report_spec()->field( $weight )->type ); } $self->{'weight'} = $weight; } $self->{'weight'}; } =pod =head2 ratio([$new_ratio]) Returns how the sum will be expressed. This can one of three possible values: =over =item none Default. The absolute sum will be used. =item group The sum will be expressed as a percentage of the group's sum. =item table The sum will be expressed as a percentage of the table's total sum. =back =cut sub ratio { my ( $self, $ratio ) = @_; if ( @_ == 2 ) { croak "invalid value for ratio attribute: $ratio, should be one of none, group or table" unless $ratio =~ /^(none|group|table)$/; $self->{'ratio'} = $ratio; } $self->{'ratio'}; } #------------------------------------------------------------------------ # Method xml_attrs() # # Implementation needed by Lire::Aggregate sub xml_attrs { my ($self) = @_; my $attr = $self->SUPER::xml_attrs; $attr .= qq{ weight="$self->{'weight'}"} if defined $self->{'weight'}; $attr .= qq{ ratio="$self->{'ratio'}"}; $attr; } # Implements Lire::SimpleStat::sql_aggr_expr sub sql_aggr_expr { my $self = $_[0]; my $sum_expr = sql_quote_name( $self->{'field'} ); $sum_expr .= "*" . sql_quote_name( $self->{'weight'} ) if defined $self->{'weight'}; return 'sum(' . $sum_expr . ')'; } # Overrides Lire::SimpleStat::sql_required_fields sub sql_required_fields { my $self = $_[0]; my @fields = ( $self->{'field'} ); push @fields, $self->{'weight'} if defined $self->{'weight'}; return \@fields; } # Implements Lire::Aggregate::create_value() sub create_value { my ( $self, $parent_group, $row ) = @_; my %value; my $name = $self->name(); $value{'value'} = $row->{$name}; $self->set_missing_cases_value( $row, \%value ); if ( $self->{'ratio'} eq 'none' ) { $value{'content'} = format_numeric_type( $row->{$name}, $self->dlf_field()->type() ); } else { my $group_sum = $self->_get_ratio_denominator( $parent_group );; my $total = defined $group_sum->{'value'} ? $group_sum->{'value'} : $row->{$name}; $value{'content'} = ratio100( $row->{$name}, $total ); } return \%value; } sub _get_ratio_denominator { my ( $self, $parent_group ) = @_; return ( $self->{'ratio'} eq 'table' || ! $parent_group->parent_entry() ) ? $parent_group->subreport()->get_summary_value( $self->name()) : $parent_group->get_summary_value( $self->name() ); } # Implements Lire::ReportOperator::merge_group_data() sub merge_group_data { my ( $self, $value, $data ) = @_; # To merge two sums, we simply add them $$data += $value->{'value'}; return; } # Implements Lire::Aggregate::data2dlf() sub data2dlf { my ($self, $data) = @_; my $name = $self->name(); return { "$name" => $$data, "_lr_${name}_mc" => $self->missing_cases( $data ), }; } # keep perl happy 1; __END__ =head1 SEE ALSO zLire::ReportSpec(3pm), Lire::ReportOperator(3pm), Lire::Aggregator(3pm), Lire::Aggregate(3pm). =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Sum.pm,v 1.17 2008/03/09 19:27:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001, 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartType.pm����������������������������������������������������������������0000644�0001750�0001750�00000021166�10462721152�014047� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ChartType; use strict; use base qw/Lire::Plugin/; use Lire::Utils qw/check_param check_object_param tempdir shell_quote file_content/; use Carp; =pod =head1 NAME Lire::ChartType - Base interface for all ChartType. =head1 SYNOPSIS use base qw/ Lire::ChartType /; =head1 DESCRIPTION This package defines the interface which is implemented by all the different charts that Lire is able to produce using the ploticus pl(1) command. A chart type will generate a chart using data from a subreport. =head1 META INFORMATION METHODS The Lire::ChartType interface extends the Lire::Plugin interface, so they must implement all standard meta-information methods (name(), title(), description()). =cut sub type { return 'chart_type' } =head1 GENERATING A CHART =head2 write_chart( $chart_config, $subreport, [ %params ] ) This will write a chart from the data contained in the Lire::Report::Subreport $subreport using the configuration $chart_config. Additional parameters are passed in 'key' => $value form. The $chart_config parameters should be a Lire::Config::Dictionary object instantiated from a Lire::Config::ChartSpec. =over 4 =item outputdir Directory where the file will be created. Use the working directory by default. =item format One of eps, png, jpeg or gif. Default to the configuration variable lr_image_format. =back The function returns the path to the created file. The filename is generated base on the 'name' configuration value or the subreport's id if the other isn't defined. The extension is added based on the output format. It returns the file where the chart was written. =cut sub write_chart { my ( $self, $chart_config, $subreport, %params ) = @_; check_object_param( $subreport, 'subreport', 'Lire::Report::Subreport' ); check_object_param( $chart_config, 'chart_config', 'Lire::Report::ChartConfig' ); $params{'format'} ||= Lire::Config->get( 'lr_image_format' ); check_param( $params{'format'}, 'format', qr/^(eps|gif|jpeg|png)$/, "'format' should be one of 'eps', 'gif', 'jpeg' or 'png'" ); $params{'errfile'} = tempdir( 'Lire::ChartType_XXXXXX', 'CLEANUP' => 1 ) . "/errfile"; $params{'outputdir'} ||= '.'; croak "cannot write to directory '$params{'outputdir'}" unless -d $params{'outputdir'} && -w $params{'outputdir'}; croak "'ploticus_path' configuration variable isn't valid" unless Lire::Config->get_var( 'ploticus_path' )->is_valid(); $subreport->table_info()->set_variables_indices(); croak "invalid chart configuration" unless $chart_config->is_valid(); return undef unless $subreport->entries(); $params{'outputfile'} = $self->_outputfile( $chart_config, $subreport, \%params ); my $cmdline = $self->_pl_cmdline( \%params ); open my $pl, "|$cmdline" or die "failed to fork: $!\n"; $self->write_parameters( $chart_config, $pl ); $self->write_data( $chart_config, $subreport, $pl ); die "Ploticus error: " . file_content( $params{'errfile'} ) unless close $pl; return $params{'outputfile'}; } sub _outputfile { my ( $self, $chart_cfg, $subreport, $params ) = @_; return $params->{'outputdir'} . "/" . ( $chart_cfg->get( 'name' )->as_value() || $subreport->id() ) . "." . ( $params->{'format'} eq 'jpeg' ? 'jpg' : $params->{'format'} ); } sub _pl_cmdline { my ( $self, $params ) = @_; $params->{'font'} ||= Lire::Config->get( 'lr_chart_font' ); return join( " ", Lire::Config->get( 'ploticus_path' ), $self->prefab(), 'data=-', 'delim=tab', 'header=yes', "-$params->{'format'}", "-o", shell_quote( $params->{'outputfile'} ), ( $params->{'font'} ? ( '-font', shell_quote( $params->{'font'}) ) : '' ), "2>", $params->{'errfile'} ); } =pod =head2 prefab() This method must be implemented by the subclass and should return a string representing the first parameters to pass to ploticus (that is either -prefab name or the path to a script file). =cut sub prefab { croak ref shift, "::get_vars unimplemented"; } =pod =head2 write_parameters( $chart_config, $fh ) This method is used to write parameters to the ploticus file handle. This is the place to use the #set command to set all of the prefabs parameters. Subclass must chain to this implementation for the standard chart parameters. It also write '#set name' directives for each numerical variables defined by get_vars(). =cut sub write_parameters { my ( $self, $chart_config, $fh ) = @_; print $fh "#set x = 1\n"; my $title = $chart_config->get( 'title' )->as_value(); print $fh "#set title = $title\n" if $title; my $xlabel = $chart_config->get( 'xlabel' )->as_value(); print $fh "#set xlbl = $xlabel\n" if $xlabel; my $ylabel = $chart_config->get( 'ylabel' )->as_value(); print $fh "#set ylbl = $ylabel\n" if $ylabel; my $idx = 1; foreach my $var ( @{$self->get_vars( $chart_config )} ) { next if $var->class() eq 'categorical'; my $name = $idx == 1 ? 'name' : 'name' . $idx; print $fh "#set $name = ", $var->label(), "\n"; $idx++; } return; } =pod =head2 write_data( $chart_config, $subreport, $fh ) This method is used by the write_chart() implementation to write the chart data from $subreport to the Ploticus commond opened on $fh. It uses the get_vars() method to obtain the numerical variables that should be written to the stream and the encode_value() method to marshall values before writing them. Before any data is written to $fh the maximum value on the Y axis is determined and output as a ploticus setting. (ploticus fails if this is not set, a single bar is drawn and the value is greater than 1.1e9.) =cut sub write_data { my ( $self, $chart_config, $subreport, $fh ) = @_; my $case_var = $chart_config->get( 'case_var' )->as_value(); my @vars = ( $case_var, @{ $self->get_vars( $chart_config ) } ); print $fh join( "\t", map { $_->name() } @vars ), "\n"; my @slice = map { $_->col_start() } @vars; my @rows = (); for ( my $i=0; $i < $subreport->nrows(); $i++ ) { my $row = $subreport->getrow_by_idx( $i ); next unless defined $row->[ $case_var->col_start() ]; push @rows, [ map { $self->encode_value( $_ ) } @{$row}[@slice] ]; } my $yrange = -1; foreach my $ro (@rows) { my ($x, @values) = @{$ro}; foreach my $value (@values) { $yrange = $value if( $value =~ /^[+-]?[0-9]+\.?[0-9]*(e[+-]?[0-9]+)?$/ && $value > $yrange ); } } if( $yrange > 0 ) { print $fh "#set yrange 0 $yrange\n"; } else { print $fh "#set yrange 0\n"; } foreach my $r (@rows) { print $fh join( "\t", @{$r} ), "\n"; } return ; } =pod =head2 get_vars( $chart_config ) This method should be overriden by subclasses to return an array reference containing the Lire::Report::ColumnInfo specifying the numerical column's of data that should be written. This is usually specified using a ReferenceSpec with the 'numerical_variables' index. These variables will start at the ploticus index 2 (@2). =cut sub get_vars { croak ref shift, "::get_vars unimplemented"; } =pod =head2 encode_value( $value ) By default, this method just returns the 'content' component of the item when the $value is a name and the 'value' component otherwise. It can used for data type that needs special encoding (like datetime). =cut sub encode_value { return $_[1]{'type'} eq 'name' ? $_[1]{'content'} : ( $_[1]{'value'} eq 'NaN' ? 'NA' : $_[1]{'value'} ); } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::Config::ChartSpec(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: ChartType.pm,v 1.17 2006/07/29 18:01:14 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Timegroup.pm����������������������������������������������������������������0000644�0001750�0001750�00000037752�10460673256�014140� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Timegroup; use strict; use base qw/ Lire::Aggregator /; use Carp; use POSIX qw/ setlocale strftime LC_TIME /; use Lire::DataTypes qw/ check_duration daily_duration duration2sec monthly_duration weekly_duration yearly_duration/; use Lire::Utils qw/ sql_quote_name check_param /; =pod =head1 NAME Lire::Timegroup - Base class for implementation of the timegroup aggregator =head1 SYNOPSIS use Lire::Timegroup; =head1 DESCRIPTION This module is the base class for implementation of the timegroup aggregator. This aggregator will split the DLF records based on a time period controlled throught the period attribute. For example, using 1d as the period value, this aggregator will group all records in the same day period together. =head1 CONSTRUCTOR =head2 new( %params ) Creates a new instance of a timegroup aggregator. In addition to the normal report operator parameters, the timegroup aggregator can take several parameters: =over =item field This optional parameter contains the DLF field which contains the time value used to group the DLF records together. See the field() method for more information. =item period This mandatory parameter should contains the period's length that will be used to group the records. See the period() method for more information. =back =cut sub new { my ( $class, %params ) = @_; check_param( $params{'period'}, 'period' ); my $self = bless {}, $class; $self->SUPER::init( %params, 'op' => "timegroup" ); $self->field( $params{'field'} ); $self->period( $params{'period'} ); return $self; } =pod =head1 METHODS =head2 field( [$new_field] ) Returns the DLF field's name that is used to group the DLF records. This should be a valid timestamp DLF field in the current schema. By default, the default timestamp field of the DLF schema is used. You can change the field by passing a $new_field parameter. =cut sub field { my ( $self, $field ) = @_; if (@_ == 2 ) { if ( defined $field ) { croak "'$field' isn't a valid field for the specification's schemas" unless $self->report_spec()->has_field( $field ); croak "'$field' isn't a timestamp field" unless $self->report_spec()->field( $field )->type() eq "timestamp"; } else { $field = $self->report_spec()->schema()->timestamp_field()->name(); } $self->{'field'} = $field; } return $self->{'field'}; } =pod =head2 period( [$new_period]) Returns the period's length in which the records are grouped. This can either be a duration value or the name of a report specification's parameter containing a duration value. The period's length can be changed by using the $new_period parameter. =cut sub period { my ( $self, $period ) = @_; if (@_ == 2 ) { check_param( $period, 'period' ); if ( $period =~ /^\$/ ) { my $name = substr $period, 1; croak "parameter '$name' isn't defined" unless $self->report_spec()->has_param( $name ); my $type = $self->report_spec()->param( $name )->type(); croak "parameter '$name' isn't a 'duration' parameter: '$type'" unless $type eq "duration"; } else { croak "'period' parameter isn't a valid duration: '$period'" unless check_duration( $period ); } my $value = $self->report_spec()->resolve_param_ref( $period ); croak "can't use multiple with period of type 'd'" unless ( !daily_duration( $value ) || $value =~ m/^\s*1\s*d/ ); #1 $self->{'period'} = $period; } return $self->{'period'}; } # Implements Lire::ReportOperator::name sub name { return "timegroup:" . $_[0]->{'field'}; } # ------------------------------------------------------------------------ # Method create_categorical_info( $info ) # # Implementation of the method required by Lire::Aggregator sub create_categorical_info { my ( $self, $info ) = @_; my $dlf_field = $self->report_spec()->field( $self->field() ); $info->create_column_info( $self->name(), 'categorical', $dlf_field->type(), $self->label() ); } # ------------------------------------------------------------------------ # Method xml_attrs( $info ) # # Implementation of the method required by Lire::Aggregator sub xml_attrs { my ( $self ) = @_; return "field=\"$self->{'field'}\" period=\"$self->{'period'}\""; } sub build_query { my ( $self, $query ) = @_; $self->SUPER::build_query( $query ); my $period = $self->report_spec()->resolve_param_ref( $self->{'period'} ); my ( $mult, $unit ) = $period =~ /(\d+)\s*(\w)/; my ($func, $param); if ( $unit eq 'y' ) { ( $func, $param ) = ('lr_timegroup_year', ",$mult" ); } elsif ( $unit eq 'M' ) { ( $func, $param ) = ('lr_timegroup_month', ",$mult" ); } elsif ( $unit eq 'w' ) { ( $func, $param ) = ('lr_timegroup_week', ",$mult" ); } elsif ( $unit eq 'd' ) { ( $func, $param ) = ( 'lr_timegroup_day', '' ); } else { $mult = duration2sec( $period ); ( $func, $param ) = ('lr_timegroup_sec', ",$mult" ); } $query->add_group_field( $self->name(), sprintf( '%s(%s%s)', $func, sql_quote_name( $self->{'field'} ), $param) ); $query->set_sort_spec( $self->name() ); return; } sub create_entry { my ( $self, $group, $row ) = @_; my $entry = $group->create_entry(); my $value = $row->{ $self->name() }; unless ( defined $value ) { $group->missing_cases( $row->{'_lr_nrecords'} ); return undef; } my $period = $self->report_spec()->resolve_param_ref( $self->{'period'} ); my $period_sec = duration2sec( $period ); my ( $mult, $unit ) = $period =~ /(\d+)\s*(\w)/; my $fmt; if ( $unit eq 'y' ) { $fmt = '%Y'; } elsif ( $unit eq 'M' ) { $fmt = '%B %Y'; } elsif ( $unit eq 'w' ) { $fmt = new Lire::WeekCalculator()->strformat(); } elsif ( $unit eq 'd' ) { $fmt = '%Y-%m-%d'; } elsif ($self->_is_day_change( $group, $value ) ){ $fmt = '%Y-%m-%d %H:%M';} else { $fmt = ' %H:%M'; } my $old_locale = setlocale( LC_TIME, 'C' ); $entry->add_name( strftime( $fmt, localtime $value), $value, $period_sec ); setlocale( LC_TIME, $old_locale ); return $entry; } sub _is_day_change { my ( $self, $group, $value ) = @_; my @entries = $group->entries(); return 1 unless @entries > 1; # -1 is the entry currently being created my $name = $entries[-2]->data_by_name( $self->name() ); my $new_day = (localtime $value)[3]; my $old_day = (localtime $name->{'value'})[3]; return $new_day != $old_day; } # Implements Lire::ReportOperator::init_merge() sub init_merge { my $self = $_[0]; $self->SUPER::init_merge(); my $period = $self->report_spec()->resolve_param_ref( $self->period() ); $self->{'period_sec'} = duration2sec( $period ); my ( $multiple ) = $period =~ /^(\d+)/; if ( monthly_duration( $period ) ) { $self->{'helper'} = Lire::Timegroup::MonthHelper->new( $self->{'period_sec'}, $multiple); } elsif (weekly_duration( $period ) ) { $self->{'helper'} = Lire::Timegroup::WeekHelper->new( $self->{'period_sec'}, $multiple); } elsif ( yearly_duration( $period ) ) { $self->{'helper'} = Lire::Timegroup::YearHelper->new( $self->{'period_sec'}, $multiple ); } else { $self->{'helper'} = Lire::Timegroup::SecHelper->new( $self->{'period_sec'}, $multiple ); } $self->{'_merge_started'} = 0; return; } sub init_slice_data { my ( $self, $idx ) = @_; my $data = [ $self->{'helper'}->slice_start( $idx ) ]; my $i = 1; foreach my $op ( @{$self->ops()} ) { $data->[$i++] = $op->init_group_data(); } return $data; } # Implements Lire::Aggregator::init_aggregator_data() sub init_aggregator_data { return []; } # Implements Lire::Aggregator::merge_aggregator_data() sub merge_aggregator_data { my ( $self, $group, $timeslices ) = @_; # INVARIANT: entries are assumed to be sorted on timestamp and the # length attribute will be identical across all the entries. This # is respected by our create_group_entries() method my $first = 1; foreach my $e ( $group->entries() ) { my @names = $e->names(); die "invalid number of names for a timegroup aggregator: ", scalar @names, "\n" if @names != 1; my $time = $names[0]{'value'}; # Check period compatibility $self->{'start'} if ( $first ) { my $length = $names[0]{'range'}; croak "incompatible merge: source period isn't compatible ", "with new period: source=$length; target=$self->{'period_sec'}\n" if $self->{'period_sec'} < $length || $self->{'period_sec'} % $length; $first = 0; unless ( $self->{'_merge_started'} ) { $self->{'helper'}->init( $time ); $self->{'_merge_started'} = 1; } } my $idx = $self->{'helper'}->find_idx( $time ); if ( $idx < 0 ) { unshift @$timeslices, (undef) x abs $idx; $self->{'helper'}->init( $time ); $idx = 0; } my $data = $timeslices->[$idx]; $timeslices->[$idx] = $data = $self->init_slice_data( $idx ) unless defined $data; my $i = 1; foreach my $op ( @{$self->ops()} ) { my $value = $e->data_by_name( $op->name() ); my $op_data = $data->[$i++]; $op->merge_group_data( $value, $op_data ) if ( $value ); } } return; } # Implements Lire::Aggregator::end_aggregator_data() sub end_aggregator_data { my ( $self, $timeslices ) = @_; for ( my $i=0; $i < @$timeslices; $i++ ) { # Create empty set $timeslices->[$i] = $self->init_slice_data( $i ) unless $timeslices->[$i]; my $data = $timeslices->[$i]; my $j = 1; foreach my $op ( @{$self->ops()} ) { $op->end_group_data( $data->[$j++] ); } } return; } # Implements Lire::Aggregator::create_group_entries() sub create_group_entries { my ( $self, $group, $timeslices ) = @_; foreach my $tslice ( @$timeslices ) { my $row = { $self->name() => $tslice->[0] }; my $entry = $self->create_entry( $group, $row ); my $i = 1; foreach my $op ( @{$self->ops()} ) { $op->add_entry_value( $entry, $tslice->[$i++] ); } } return; } package Lire::Timegroup::Helper; sub new { my ( $class, $period, $multiple ) = @_; return bless { 'period' => $period, 'multiple' => $multiple, }, $class; } package Lire::Timegroup::SecHelper; use base qw/Lire::Timegroup::Helper/; use Time::Timezone; use POSIX qw/floor/; sub init { my ( $self, $start ) = @_; $self->{'start'} = int( $start / $self->{'period'} ) * $self->{'period'}; # The start of the period is offset by the timezone offset. We # need only do this once, because UTC doesn't have a standard vs. # daylight saving issue. my $offset = tz_local_offset( $self->{'start'} ); $self->{'start'} -= $offset if abs($offset) < $self->{'period'}; return; } sub find_idx { my ( $self, $time ) = @_; return floor( ($time - $self->{'start'}) / $self->{'period'} ); } sub slice_start { my ( $self, $idx ) = @_; return $idx * $self->{'period'} + $self->{'start'}; } package Lire::Timegroup::WeekHelper; use base qw/Lire::Timegroup::Helper/; use Lire::WeekCalculator; use POSIX qw/floor/; sub week_year { my ( $week_idx, $time ) = @_; my ( $month, $year ) = (localtime( $time ))[4,5]; # ISO: Last week of December as week 01 of next year $year++ if $month == 11 && $week_idx == 0; # All: First week of january as week 52 or 53 $year-- if $month == 0 && $week_idx > 50; return $year + 1900; } sub init { my ( $self, $start ) = @_; $self->{'week_calc'} = new Lire::WeekCalculator(); $self->{'week_start'} = $self->{'week_calc'}->week_idx( $start ); $self->{'year_start'} = week_year( $self->{'week_start'}, $start ); return; } sub find_idx { my ( $self, $time ) = @_; my $week_idx = $self->{'week_calc'}->week_idx( $time ); my $year = week_year( $week_idx, $time ); my $year_diff = $year - $self->{'year_start'}; my $idx; if ( $year_diff > 0 ) { $idx = -$self->{'week_start'}; for ( my $i=$self->{'year_start'}; $i < $self->{'year_start'}; $i++ ) { $idx += $self->{'week_calc'}->last_week_of_year( $i ); } } elsif ( $year_diff < 0 ) { $idx = -$self->{'week_start'}; for ( my $i=$self->{'year_start'}-1; $i > $year; $i-- ) { $idx -= $self->{'week_calc'}->last_week_of_year( $i ); } $idx -= $self->{'week_calc'}->last_week_of_year( $year ) - $week_idx; } elsif ( $year_diff == 0 && $week_idx < $self->{'week_start'} ) { $idx = - ( $self->{'week_start'} - $week_idx ); } else { $idx = $week_idx - $self->{'week_start'}; } return floor( $idx / $self->{'multiple'} ); } sub slice_start { my ( $self, $idx ) = @_; my $week_idx = $idx * $self->{'multiple'}; my $year = $self->{'year_start'}; my $year_week = $self->{'week_calc'}->last_week_of_year( $year ); if ( $week_idx > ( $year_week - $self->{'week_start'} ) ) { $week_idx -= $year_week - $self->{'week_start'}; $year++; while ( $week_idx > $self->{'week_calc'}->last_week_of_year( $year ) ) { $week_idx -= $self->{'week_calc'}->last_week_of_year( $year ); $year++; } } else { $week_idx += $self->{'week_start'}; } return $self->{'week_calc'}->week_start( $year, $week_idx + 1 ); } package Lire::Timegroup::MonthHelper; use base qw/Lire::Timegroup::Helper/; use Time::Local; use POSIX qw/floor/; sub init { my ( $self, $start ) = @_; my ($month,$year) = (localtime( $start ))[4,5]; $self->{'month_start'} = $month; $self->{'year_start'} = $year; return; } sub find_idx { my ( $self, $time ) = @_; my ($month,$year) = (localtime( $time ))[4,5]; my $year_diff = $year - $self->{'year_start'}; my $idx = 12 * $year_diff - $self->{'month_start'} + $month; return floor( $idx / $self->{'multiple'} ); } sub slice_start { my ( $self, $idx ) = @_; my $month = $idx * $self->{'multiple'} + $self->{'month_start'}; my $year_offset = int( $month / 12 ); $month -= $year_offset * 12; return timelocal( 0, 0, 0, 1, $month, $self->{'year_start'} + $year_offset ); } package Lire::Timegroup::YearHelper; use base qw/Lire::Timegroup::Helper/; use Time::Local; use POSIX qw/floor/; sub init { my ( $self, $start ) = @_; $self->{'start'} = (localtime( $start ))[5]; return; } sub slice_start { my ( $self, $idx ) = @_; my $year_off = $idx * $self->{'multiple'}; return timelocal( 0, 0, 0, 1, 0, $self->{'start'} + $year_off ); } sub find_idx { my ( $self, $time ) = @_; my $year = (localtime( $time ))[5]; return floor( ($year - $self->{'start'}) / $self->{'multiple'} ); } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::Group(3pm), Lire::ReportOperator(3pm), Lire::Timeslot(3pm) =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <Wolfgang.Sourdeau@Contre.COM> =head1 VERSION $Id: Timegroup.pm,v 1.33 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ����������������������lire-2.1.1/all/lib/Lire/Rangegroup.pm���������������������������������������������������������������0000644�0001750�0001750�00000042301�10463107351�014247� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Rangegroup; use strict; use base qw/ Lire::Aggregator /; use Carp; use POSIX; use constant NEGLIGIBLE_QTY => 0.000001; use Lire::DataTypes qw/ check_bytes check_duration check_number duration2sec size2bytes format_numeric_type is_quantity_type /; use Lire::Utils qw/ sql_quote_name /; =pod =head1 NAME Lire::Group - Base class for implementation of the rangegroup aggregator =head1 SYNOPSIS use Lire::Rangegroup; =head1 DESCRIPTION This module is the base class for implementation of the rangegroup aggregator. This aggregator will split the DLF records based on a numerical field. The so-called range groups creates numerical classes (e.g. 1-10, 11-20, etc.) and the DLF record will be grouped with other records which are in the same class. =head1 CONSTRUCTOR =head2 new( %params ) Creates a new instance of a group aggregator. In addition to the normal report operator parameters, the rangegroup aggregator can take several parameters: =over =item field This parameter is mandatory. It should be the name of the DLF field which will be used as key for this aggregator. =item range-size This parameter is mandatory. This will be used as the size of each range group. =item range-start The number at which the first range group starts. Defauls to 0. =item min-value Value lower than this number will be sorted in the first range group. =item max-value Value higher than this number will be sorted in the last range group. =item size-scale This parameter can be used to create a logarithmic scale. In this case, each new range group will be size-scale bigger than the one that comes before it. For example, setting range-size=5 and size-scale=2 will create ranges like [0-5>, [5-15>, [15-35>, ... =back =cut sub new { my $proto = shift; my $class = ref( $proto) || $proto; my %params = @_; my $self = bless {}, $class; $self->SUPER::init( %params, 'op' => "rangegroup" ); croak "missing 'field' attribute" unless exists $params{'field'}; $self->field( $params{'field'} ); croak "missing 'range-size' attribute" unless exists $params{'range-size'}; $self->range_size( $params{'range-size'} ); $self->range_start( $params{'range-start'} || 0 ); $self->min_value( $params{'min-value'} ) if exists $params{'min-value'}; $self->max_value( $params{'max-value'} ) if exists $params{'max-value'}; $self->size_scale( $params{'size-scale'} || 1 ); return $self; } =pod =head1 METHODS =head2 field( [$new_field] ) Returns the name of the DLF field which is used as grouping key. If the $new_field parameter is set, it changes the grouping field. This must be the name of a quantity type field in the report specifications DLF schema. =cut sub field { my ( $self, $field ) = @_; if (defined $field) { croak "'$field' isn't a field in the specification's schemas" unless $self->report_spec()->has_field( $field ); croak "'$field' isn't a bytes, duration, int or number field" unless is_quantity_type( $self->report_spec()->field( $field )->type() ); $self->{'field'} = $field; } return $self->{'field'}; } #------------------------------------------------------------------------ # Method set_attr_value( $attr_name, $value ) # # Method used to share the logic of validating the attributes' value. sub set_attr_value { my ( $self, $attr_name, $value ) = @_; my $field = $self->field(); my $type = $self->report_spec()->field( $field )->type(); if ( $value =~ /^\$/ ) { my $name = substr $value, 1; croak "$value isn't a defined parameter" unless $self->report_spec()->has_param( $name ); croak "'$attr_name' attribute: '$value' should be of type $type" if $self->report_spec()->param( $name )->type() ne $type; } elsif ( $type eq 'duration' ) { croak "invalid duration value for '$attr_name' attribute: $value" unless check_duration( $value ); } elsif ($type eq 'bytes' ) { croak "invalid bytes value for '$attr_name' attribute: $value" unless check_bytes( $value ); } else { croak "invalid numeric value for '$attr_name' attribute: $value" unless check_number( $value ); } $attr_name =~ s/-/_/g; $self->{$attr_name} = $value; return; } =pod =head2 range_start( [$new_start] ) Returns the number which is the starting bound of the first range group. If the $new_start parameter is set, it changes the starting bound of the first range group. This should either be a positive integer or the name of one of the report specification's parameter. =cut sub range_start { my ( $self, $start ) = @_; $self->set_attr_value( 'range-start', $start || 0 ) if @_ == 2; return $self->{'range_start'}; } =pod =head2 range_size( [$new_size] ) Returns the width of each range group. If the $new_size parameter is set, it changes the width of each range group. This should either be a positive integer or the name of one of the report specification's parameter. =cut sub range_size { my ( $self, $size ) = @_; $self->set_attr_value( 'range-size', $size ) if (defined $size ); return $self->{'range_size'}; } =pod =head2 min_value( [$new_min] ) Returns the number below which no new range groups will be created. If the $new_min is set, it changes the lower bound below which no new groups will be created. This should either be a number or the name of one of the report specification's parameter. =cut sub min_value { my ( $self, $min ) = @_; if ( @_ == 2) { if ( defined $min ) { $self->set_attr_value( 'min-value', $min ); } else { delete $self->{'min_value'}; } } return $self->{'min_value'}; } =pod =head2 max_value( [$new_max] ) Returns the number above which no new range groups will be created. If the $new_max is set, it changes the upper bound above which no new groups will be created. This should either be a number or the name of one of the report specification's parameter. =cut sub max_value { my ( $self, $max ) = @_; if ( @_ == 2) { if ( defined $max ) { $self->set_attr_value( 'max-value', $max ); } else { delete $self->{'max_value'}; } } return $self->{'max_value'}; } =pod =head2 size_scale( [$new_size_scale] ) Returns the multiplier that will be apply to each of the range group's width after the first one. When this attribute is greater than 1, it creates a logarithmic scale where each new ranges is $size_scale wider than the precedent one. If the $new_size_scale parameter is used, it changes the attribute to this new value. It should be a positive interger or can also be a parameter reference. =cut sub size_scale { my ( $self, $size_scale ) = @_; if ( @_ == 2 ) { if ( defined $size_scale ) { if ( $size_scale =~ /^\$/ ) { my $name = substr $size_scale, 1; croak "$size_scale isn't a defined parameter" unless $self->report_spec->has_param( $name ); croak "'size-scale' attribute must be a number type" unless $self->report_spec->param( $name )->type() ne 'number'; } else { croak "invalid 'size-scale' value. It should be a number" unless check_number( $size_scale ); } $self->{'size_scale'} = $size_scale; } else { delete $self->{'size_scale'}; } } return $self->{'size_scale'}; } # ------------------------------------------------------------------------ # Method xml_attrs() # # Implementation required by Lire::Aggregator sub xml_attrs { my ( $self ) = @_; return qq{field="$self->{'field'}" range-start="$self->{'range_start'}" range-size="$self->{'range_size'}"}; } # Implements Lire::ReportOperator::name() sub name { return 'rangegroup:' . $_[0]->{'field'}; } # ------------------------------------------------------------------------ # Method create_categorical_info( $info ) # # Implementation of the method required by Lire::Aggregator sub create_categorical_info { my ( $self, $info ) = @_; my $dlf_field = $self->report_spec()->field( $self->field() ); $info->create_column_info( $self->name(), 'categorical', $dlf_field->type(), $self->label() ); return; } sub build_query { my ( $self, $query ) = @_; $self->SUPER::build_query( $query ); my $scale = $self->_param_value( 'size_scale' ); my $func = ( $scale == 1) ? "lr_rangegroup" : "lr_rangegroup_geo"; my @params; foreach my $p ( qw/range_start range_size size_scale min_value max_value/ ) { my $value = $self->_param_value( $p ); next if ( $p eq 'size_scale' && $value == 1 ); push @params, defined $value ? $value : 'NULL'; } $query->add_group_field( $self->name(), sprintf( '%s(%s,%s)', $func, sql_quote_name( $self->{'field'} ), join( ",", @params) ) ); $query->set_sort_spec( $self->name() ); return; } sub _param_value { my ( $self, $param ) = @_; my $value = $self->{$param}; return undef unless defined $value; $value = $self->report_spec()->resolve_param_ref( $value ); my $type = $self->report_spec()->field( $self->{'field'} )->type(); if ( $type eq 'bytes' ) { return size2bytes( $value ); } elsif ( $type eq 'duration' ) { return duration2sec( $value ); } else { return $value; } return 0; } sub create_entry { my ( $self, $group, $row ) = @_; my $value = $row->{ $self->name() }; unless ( defined $value ) { $group->missing_cases( $row->{'_lr_nrecords'} ); return undef; } # create entry after all checks to avoid empty entries in group # (empty entries make XML merge fail) my $entry = $group->create_entry(); my $length = $self->_param_value( 'range_size' ); my $start = $self->_param_value( 'range_start'); my $scale = $self->_param_value( 'size_scale' ); while ( $value < $start || $value >= ( $start + $length ) ) { $start += $length; $length *= $scale; } my $type = $self->report_spec()->field( $self->{'field'} )->type(); my $content = sprintf( '[%s-%s>', format_numeric_type( $start, $type ), format_numeric_type( ( $start + $length ), $type )); $entry->add_name( $content, $value, $length ); return $entry; } # Implements Lire::ReportOperator::init_merge() sub init_merge { my $self = $_[0]; $self->SUPER::init_merge(); $self->{'_m_min_value'} = $self->_param_value( 'min_value' ); $self->{'_m_max_value'} = $self->_param_value( 'max_value' ); $self->{'_m_size_scale'} = $self->_param_value( 'size_scale' ); die "'size-scale' must be a positive number: $self->{'_m_size_scale'}\n" unless $self->{'_m_size_scale'} >= 0; $self->{'_m_range_start'} = $self->_param_value( 'range_start' ); $self->{'_m_range_size'} = $self->_param_value( 'range_size' ); die "'range-size' attribute's value should be positive: $self->{'_m_range_size'}\n" unless $self->{'_m_range_size'} >= 0; return; } # Implements Lire::Aggregator::init_aggregator_data() sub init_aggregator_data { my $self = $_[0]; my $ranges = []; # Transform the min_value in the range_start parameter $self->{'_m_range_start'} = $self->{'_m_min_value'} - $self->{'_m_range_start'} if ( defined $self->{'_m_min_value'}); if ( defined $self->{'_m_max_value'}) { my $end_idx; if ( $self->{'_m_size_scale'} == 1 ) { $end_idx = int( ($self->{'_m_max_value'} - $self->{'_m_range_start'}) / $self->{'_m_range_size'}); } else { $end_idx = 0; my $end = $self->{'_m_range_start'}; while (1) { $end += (($self->{'_m_size_scale'} ** $end_idx) * $self->{'_m_range_size'}); last if $self->{'_m_max_value'} < $end; $end_idx++; } } # Make sure that we have entry until max_value $ranges->[$end_idx] = undef; } return $ranges; } # Implements Lire::Aggregator::merge_aggregator_data() sub merge_aggregator_data { my ( $self, $group, $ranges ) = @_; foreach my $e ( $group->entries() ) { my @names = $e->names(); die "invalid number of names for a rangegroup subreport: ", scalar @names, "\n" if @names != 1; # FIXME: We won't interpolate data. So for merging to succeed # the whole class must be contained in the new class. # # Another possible way to merge is to use the middle of the class # to determine where the class should be merged. This would be less # accurate than the current method, but merging would never fail. my $start = $names[0]{'value'}; my $length = $names[0]{'range'}; # Clamp if necessary if ( defined $self->{'_m_min_value'} && $start < $self->{'_m_min_value'} ) { croak "incompatible merging parameters: ", "range is splitted across min value: [$start,", $start + $length, "> <> $self->{'_m_min_value'}\n" if $start + $length > $self->{'_m_min_value'}; $start = $self->{'_m_min_value'}; $length = NEGLIGIBLE_QTY; } if ( defined $self->{'_m_max_value'} && $start > $self->{'_m_max_value'} ) { $start = $self->{'_m_max_value'}; $length = NEGLIGIBLE_QTY; } # Since the $start + $length isn't included in the range, we subtract # a negligible quantity just to make sure that it falls onto the # same idx my ($idx); if ( $self->{'_m_size_scale'} == 1 ) { $idx = int( ($start - $self->{'_m_range_start'}) / $self->{'_m_range_size'}); my $eidx = int( (($start + $length) - $self->{'_m_range_start'} - NEGLIGIBLE_QTY) / $self->{'_m_range_size'}); croak "incompatible merge: source range is splitted across ranges:", "[$start,", $start + $length, "> : start=$self->{'_m_range_start'}; ", "size=$self->{'_m_range_size'}\n" if $idx != $eidx; } else { $idx = 0; my $end = $self->{'_m_range_start'}; while (1) { $end += (($self->{'_m_size_scale'} ** $idx) * $self->{'_m_range_size'}); last if ( $end > ($start + $length) - NEGLIGIBLE_QTY ); die "incompatible merge: source range is splitted across", " target ranges: [$start,", $start + $length, "> : ", "end=$end\n" if $end > $start; $idx++; } } if ( $idx < 0 ) { croak "can't reorder ranges when using size-scale != 1. Please set min-value $!" if $self->{'_m_size_scale'} != 1; # We have ranges under the first index. Push the ranges to the right. $self->{'_m_range_start'} = $idx * $self->{'_m_range_size'} + $self->{'_m_range_start'}; @$ranges = ( (undef) x abs($idx), @$ranges ); $idx = 0; } my $data = $ranges->[$idx]; unless ( defined $data ) { $data = []; my $i = 0; foreach my $op ( @{$self->ops()} ) { $data->[$i++] = $op->init_group_data(); } $ranges->[$idx] = $data; } my $i = 0; foreach my $op ( @{ $self->ops() } ) { my $value = $e->data_by_name( $op->name ); my $op_data = $data->[$i++]; $op->merge_group_data( $value, $op_data ) if ( $value ); } } return; } # Implements Lire::Aggregator::end_aggregator_data() sub end_aggregator_data { my ( $self, $ranges ) = @_; # Finalize each ranges # Either create empty one or call end_group_data on them my $last_idx = $#$ranges; my $i = 0; while ( $i <= $last_idx) { if ( $ranges->[$i]) { my $data = $ranges->[$i]; my $j = 0; foreach my $op ( @{$self->ops} ) { $op->end_group_data( $data->[$j++] ); } } else { my $data = []; my $j = 0; foreach my $op ( @{$self->ops} ) { $data->[$j] = $op->init_group_data(); $op->end_group_data( $data->[$j++] ); } $ranges->[$i] = $data; } $i++; } return $self; } # Implements Lire::Aggregator::create_group_entries() sub create_group_entries { my ( $self, $group, $ranges ) = @_; my $start; for ( my $i=0; $i < @$ranges; $i++ ) { my $range = $ranges->[$i]; if ( $self->{'_m_size_scale'} == 1 ) { $start = $self->{'_m_range_size'} * $i + $self->{'_m_range_start'}; } else { if ( $i == 0 ) { $start = $self->{'_m_range_start'}; } else { $start += ($self->{'_m_size_scale'} ** ($i-1)) * $self->{'_m_range_size'}; } } my $row = { $self->name() => $start}; my $entry = $self->create_entry( $group, $row );; my $j = 0; foreach my $op ( @{ $self->ops() } ) { $op->add_entry_value( $entry, $range->[$j++] ); } } return; } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::Group(3pm), Lire::ReportOperator(3pm), Lire::Aggregator(3pm) =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <wsourdeau@logreport.org> =head1 VERSION $Id: Rangegroup.pm,v 1.25 2006/07/30 10:50:17 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Count.pm��������������������������������������������������������������������0000644�0001750�0001750�00000015127�10765035043�013237� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Count; use strict; use base qw/ Lire::Aggregate /; use Carp; use Lire::DataTypes qw/ format_numeric_type /; use Lire::Utils qw/ ratio100 sql_quote_name check_object_param/; =pod =head1 NAME Lire::Count - Lire class that implements the count operator =head1 SYNOPSIS use Lire::Count =head1 DESCRIPTION Class that implements the count operator. This operator counts the number of DLF records in the current group. If the fields attribute is set, the count statistics will be equals to the number of different values present in the fields specified by that attribute. Its also possible to express the count as a ratio of the total count for the group or table. =head1 METHODS =head2 new( %params ) Creates a new Lire::Count object. In addition to the values supported by its parents, the fields and ratio attributes will be initialized to the values specified in the %params argument. =cut sub new { my $self = bless { 'ratio' => 'none', }, shift; $self->init( @_, 'op' => 'count' ); my %args = @_; $self->fields( $args{'fields'} ) if exists $args{'fields'}; $self->ratio( $args{'ratio'} ) if exists $args{'ratio'}; return $self; } =pod =head2 fields( [$new_fields] ) Returns the fields for which we are counting the different values. This a reference to an array of DLF field names. If the $new_fields parameter is set, it will be used as the new $fields value. It must be an array reference and should only contains valid field names for the current report specification's schema. =cut sub fields { my ( $self, $fields ) = @_; if ( @_ == 2 ) { if ( defined $fields ) { check_object_param( $fields, 'fields', 'ARRAY' ); foreach my $f ( @$fields ) { croak "'$f' isn't a defined field in the specification's schemas" unless $self->report_spec()->has_field( $f ); } } $self->{'fields'} = $fields; } $self->{'fields'}; } =pod =head2 ratio([$new_ratio]) Returns how the count will be expressed. This can one of three possible values: =over =item none Default. The absolute count will be used. =item group The count will be expressed as a percentage of the group's count. =item table The count will be expressed as a percentage of the table's total count. =back =cut sub ratio { my ( $self, $ratio ) = @_; if ( @_ == 2 ) { croak "invalid value for ratio attribute: $ratio, should be one of none, group or table" unless $ratio =~ /^(none|group|table)$/; $self->{'ratio'} = $ratio; } $self->{'ratio'}; } #------------------------------------------------------------------------ # Method xml_attrs() # # Implementation needed by Lire::Aggregate sub xml_attrs { my ($self) = @_; my $attr = ""; if ( exists $self->{'fields'} ) { my $fields = join " ", @{$self->{'fields'}}; $attr .= qq{fields="$fields"}; } $attr .= qq{ ratio="$self->{'ratio'}"}; $attr; } # Implementats Lire::Aggregate::create_numerical_info sub create_numerical_info { my ( $self, $group_info ) = @_; $group_info->create_column_info( $self->name, 'numerical', 'int', $self->label ); } # Overrides Lire::SimpleStat::sql_required_fields sub sql_required_fields { my $self = $_[0]; return $self->{'fields'} || []; } # Implements Lire::Aggregate::sql_aggr_expr sub sql_aggr_expr { my $self = $_[0]; if (defined $self->{'fields'}) { my @fields = map { sql_quote_name( $_ ) } @{ $self->{'fields'} }; return 'lr_count_uniq(' . join (',', @fields) .')'; } else { return 'count(*)'; } } # Implements Lire::Aggregate::create_value() sub create_value { my ( $self, $parent_group, $row ) = @_; my %value; my $name = $self->name(); $value{'value'} = $row->{$name}; $self->set_missing_cases_value( $row, \%value ); if ( $self->{'ratio'} eq 'none' ) { $value{'content'} = format_numeric_type( $row->{$name}, 'int' ); } else { my $group_sum = $self->_get_ratio_denominator( $parent_group ); my $total = defined $group_sum->{'value'} ? $group_sum->{'value'} : $row->{$name}; $value{'content'} = ratio100( $row->{$name}, $total ); } return \%value; } sub _get_ratio_denominator { my ( $self, $parent_group ) = @_; return ( $self->{'ratio'} eq 'table' || ! $parent_group->parent_entry() ) ? $parent_group->subreport()->get_summary_value( $self->name()) : $parent_group->get_summary_value( $self->name() ); } # Implements Lire::ReportOperator::init_group_data sub init_group_data { my ( $self ) = @_; if ( $self->{'key_maker'} ) { return [ 0, {} ]; } else { my $scalar = 0; return \$scalar; } } # Implements Lire::ReportOperator::merge_group_data sub merge_group_data { my ( $self, $value, $data ) = @_; # FIXME: We should add a note when a key_maker was used. For # example, there is no guarentee that the sum of the number of # hosts that visited during two reports is the same than the # number of hosts calculated over the period spanned by the two # reports. # To merge two counts, we simply add them $$data += $value->{'value'}; return; } # Implements Lire::ReportOperator::end_group_data sub end_group_data { my ( $self, $data ) = @_; $data->[1] = undef if $self->{'key_maker'}; return; } # Implements Lire::Aggregate::data2dlf() sub data2dlf { my ($self, $data) = @_; my $name = $self->name(); return { "$name" => $self->{'key_maker'} ? $data->[0] : $$data, "_lr_${name}_mc" => $self->missing_cases( $data ), }; } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::ReportOperator(3pm), Lire::Aggregator(3pm), Lire::Aggregate(3pm). =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Count.pm,v 1.16 2008/03/09 19:27:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001, 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Program.pm������������������������������������������������������������������0000644�0001750�0001750�00000017140�10460673255�013560� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Program; use strict; use base qw/ Exporter /; use vars qw/ @EXPORT_OK %EXPORT_TAGS $LR_TAG $LR_ID $PROG $LR_SUPERSERVICE $LR_SERVICE $start $init_called /; use File::Basename qw/ basename /; # Make sure the all script which uses Lire::Program # also get Lire::Config inited use Lire::Config; use Lire::Error qw/ file_not_readable /; =pod =head1 NAME Lire::Program - Lire's programs common infrastructure. =head1 SYNOPSIS Any program: use Lire::Program qw/ :msg /; lr_info( "doing stuff " ); lr_debug( "debugging information" ); lr_warn( "encountered unexpected value: ", $value ); open( CFGFILE, "my.conf" ) or lr_err( "open error: ", $! ); =head1 DESCRIPTION This module should be used by all Lire programs (at least the Perl ones :-). It includes: =over =item 1. Common behavior for good integration in the Lire suite. (Output of performance information and other stuff). =item 2. Functions for portability. =item 3. Logging functions =back =head1 COMMON BEHAVIOR FOR LIRE PROGRAMS When you use the Lire::Program module, you make sure that your program will behave correctly in the Lire tool chain. This module will install BEGIN and END blocks to comply with Lire's policy. =over =item 1. Only messages in the proper logging format I<superservice> I<service> I<lr_id> I<program> I<level> I<msg> should be output. This module will install a __WARN__ signal handler that makes sure that all modules that use warn to output messages are rewritten in the proper format. See also lr_run(1). =item 2. All programs should start by a C<info> message which logs their arguments. This module takes care of this. =item 3. All programs should end by printing C<info> messages with performance statistics and the message 'ended'. Using this module takes care of this. At the end of your program the following will be output (stripped off the common information): memory stats: vsize=10688K rss=9380K majflt=406 elapsed time in seconds real=9 user=8.72 system=0.06 stopped The memory profiling information will only be output on platforms running the Linux kernel. =back =head2 COMMON VARIABLES As a convenience, you can import in your namespace using the :env tag some variables common to all Lire programs. (Note that you can also use those variables without importing them by prefixing the variables with the Lire::Program:: namespace.) =over =item $PROG The name of your program (that's the value of $0 without the directory path). =item $LR_SUPERSERVICE The superservice which you are processing, or C<all> if this information isn't available. =item $LR_SERVICE The service which you are processing, or C<all> if this information isn't specified. =item $LR_ID That's the job identifier. It should be shared by all commands in a Lire job. This is the value UNSET when none was specified. =item $LR_TAG That's the prefix to all log messages. Should correspond to $LR_SUPERSERVICE $LR_SERVICE $LR_ID $PROG =back =cut BEGIN { ($PROG) = basename( $0 ); $LR_SUPERSERVICE = $ENV{'LR_SUPERSERVICE'} || 'all'; $LR_SERVICE = $ENV{'LR_SERVICE'} || 'all'; $LR_ID = $ENV{'LR_ID'} || "UNSET"; $LR_TAG = "$LR_SUPERSERVICE $LR_SERVICE $LR_ID $PROG"; @EXPORT_OK = qw/ tempfile tempdir /; require Lire::Utils; *tempfile = \&Lire::Utils::tempfile; *tempdir = \&Lire::Utils::tempdir; require Lire::Logger; *lr_emerg = \&Lire::Logger::lr_emerg; *lr_crit = \&Lire::Logger::lr_emerg; *lr_err = \&Lire::Logger::lr_err; *lr_warn = \&Lire::Logger::lr_warn; *lr_notice = \&Lire::Logger::lr_notice; *lr_info= \&Lire::Logger::lr_info; *lr_debug= \&Lire::Logger::lr_debug; $SIG{'__WARN__'} = sub { Lire::Logger::lr_warn( @_ ); }; %EXPORT_TAGS = ( 'dlf' => [ qw/ init_dlf_converter end_dlf_converter lire_chomp / ], 'msg' => [qw/ lr_emerg lr_crit lr_err lr_warn lr_notice lr_info lr_debug/ ], 'env' => [ qw/ $PROG $LR_SUPERSERVICE $LR_SERVICE $LR_TAG $LR_ID / ], ); foreach my $tag ( keys %EXPORT_TAGS ) { Exporter::export_ok_tags( $tag ); } Lire::Config->lire_program_config_init; } =pod =head1 LOGGING FUNCTIONS The logging functions are now part of the Lire::Logger module. Consult Lire::Logger(3pm) for more information. The old names are still exported from this module by using the ':msg' tag. =head1 DLF CONVERTERS FUNCTIONS The DLF converter API is now defined in Lire::DlfConverter(3pm). The Lire::OldDlfAdapter(3pm) can be used to work with old-style DLF Converters. =cut sub init_dlf_converter { my ( $superservice ) = @_; # Empty for now $init_called = $superservice; } sub end_dlf_converter { my ( $lines, $dlflines, $errorlines ) = @_; $errorlines ||= 0; lr_err( "Lire::Program::init_dlf_converter wasn't called" ) unless $init_called; lr_info( "read $lines lines; output $dlflines DLF lines; $errorlines errors" ); $init_called = undef; } sub lire_chomp(;$) { if ( @_ == 1 ) { $_[0] =~ s/\r?\n?$//; } else { $_ =~ s/\r?\n?$//; } } # This is executed after the function were compiled BEGIN { $start = time; if ( @ARGV ) { lr_info ( "started with ", join " ", @ARGV ); } else { lr_info ( "started with no argument" ); } } # FIXME: Make this portable to other OS then Linux 2.X sub print_linux_memory_stats { my $stat_file = '/proc/self/stat'; open PROC, $stat_file or die file_not_readable( $stat_file ); my @stats = split /\s+/, <PROC>; close PROC; # Stat layout is in linux, from proc(5) # 0 pid 10 cminflt 20 itrealvalue 30 blocked # 1 comm 11 majflt 21 starttime 31 sigignore # 2 state 12 cmajflt 22 vsize 32 sigcatch # 3 ppid 13 utime 23 rss 33 wchan # 4 pgrp 14 stime 24 rlim # 5 session 15 cutime 25 startcode # 6 tty 16 cstime 26 endcode # 7 tpgid 17 counter 27 startstack # 8 flags 18 priority 28 kstkesp # 9 minflt 19 timeout 29 signal # Sanity check to see if we read the good structure die "layout of /proc/self/stat doesn't match we expect" unless $stats[0] == $$ && $stats[3] == getppid && $stats[4] == getpgrp 0; my $vsize = $stats[22] / 1024; my $rss = $stats[23] * 4; my $majflt = $stats[11]; lr_info( "memory stats: vsize=${'vsize'}K rss=${'rss'}K majflt=$majflt" ); } END { eval { print_linux_memory_stats() } if -e "/proc/self/stat"; my $real = time - $start; my ($user, $system ) = times; # Print performance data lr_info( "elapsed time in seconds real=$real user=$user system=$system" ); lr_info( "stopped" ); } 1; __END__ =pod =head1 SEE ALSO Lire::DlfSchema(3pm), lr_run(1) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Program.pm,v 1.35 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/FilterSpec.pm���������������������������������������������������������������0000644�0001750�0001750�00000005073�10460673255�014213� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::FilterSpec; use strict; use base qw/ Lire::XMLSpecContainer /; use Lire::Config; use Lire::Utils qw/check_object_param/; =pod =head1 NAME Lire::FilterSpec - Global filter specification. =head1 SYNOPSIS use Lire::FilterSpec; =head1 DESCRIPTION =head1 META INFORMATION METHODS =head2 list_specs( $superservice ) Returns an array reference containing all the filter specification type available for the $superservice superservice. =head2 has_spec( $superservice, $type ) Returns true if there is a $type specification available for the $superservice. =cut ######################################################################## # Lire::XMLSpecContainer METHODS ######################################################################## sub root_element { my ( $self ) = @_; return "global-filter-spec"; } sub spec_path { return Lire::Config->get( 'lr_filters_path' ); } sub print_children { my ( $self, $fh, $indent ) = @_; my $pfx = ' ' x $indent; print $fh "$pfx<lire:filter-spec>\n"; $self->{'filter_spec'}->print( $fh, $indent + 1); print $fh "\n$pfx</lire:filter-spec>\n\n"; return; } ######################################################################## # Lire::FilterSpec METHODS ######################################################################## sub filter_spec { my ( $self, $filter_spec ) = @_; if ( @_ == 2 ) { check_object_param( $filter_spec, 'filter_spec', 'Lire::FilterExpr' ); $self->{'filter_spec'} = $filter_spec; } return $self->{'filter_spec'}; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::ReportConfig(3pm), Lire::ReportSection(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: FilterSpec.pm,v 1.16 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/DlfCategoriser.pm�����������������������������������������������������������0000644�0001750�0001750�00000011205�10460673254�015041� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::DlfCategoriser; use strict; use base qw/Lire::DlfAnalyser/; use Carp; =pod =head1 NAME Lire::DlfCategoriser - Base class for analysers which produce extended DLF records. =head1 SYNOPSIS use base qw/ Lire::DlfCategoriser /; sub categorise { my ( $self, $dlf ) = @_; # Adds the extended field to DLF. return; } =head1 DESCRIPTION This package defines a base class that can be use for Lire::DlfAnalyser which writes to an ExtendedSchema. The categoriser only have to implement the categorise() method instead of the more generic analyse(). =head1 META INFORMATION METHODS The Lire::DlfCategoriser should implement the same meta-information methods than the Lire::DlfAnalyser (name(), src_schema(), dst_schema(), title(), description()). =head1 IMPLEMENTATION METHODS The categoriser does its job using the initialise() and categorise() methods. =head2 analyse( $process, $config ) The Lire::DlfCategoriser implements the analyse() method. It will run the query on the src_schema() using the correct filter and will call categorise() on each DLF returned. The extended fiels will then be written to dst_schema(). Errors should be reported by dying. =cut sub analyse { my ( $self, $process, $config ) = @_; my $dst_schema = Lire::DlfSchema::load_schema( $self->dst_schema() ); croak "'" . $self->name() . "' analyser doesn't declare to write to an ExtendedSchema: '" . $self->dst_schema() . "'" unless $dst_schema->isa( 'Lire::ExtendedSchema' ); eval { $self->initialise( $config ) }; if ( $@ ) { $process->error( "Error during initialise: $@" ); return; } my $schema = Lire::DlfSchema::load_schema( $self->src_schema() ); my $query = $schema->dlf_query(); $query->set_sort_spec( $schema->timestamp_field()->name() ); my $filter = $process->source_filter(); $query->set_filter_clause( $filter->sql_expr(), @{$filter->sql_params()} ) if defined $filter; my $result = $query->execute( $process->dlf_store() ); while ( defined( my $dlf = $result->next_row() ) ) { eval { $self->categorise( $dlf ) }; if ( $@ ) { $process->error( $@ ) if $@; } else { $process->write_dlf( $dlf ); } } eval { $self->finalise( $config ) }; $process->error( "Error during initialise: $@" ) if ( $@ ); return; } =pod =head2 initialise( $config ) This method is called before the categorise() method is called. The $config parameter contains configuration data that was specified in the AnalysisJob for that analyser. To register configuration specification for you DlfCategoriser, you just need to define a configuration specification under the name I<analyser_name>_properties. This should be either a RecordSpec or ObjectSpec. =cut sub initialise { croak "initialise() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 categorise( $dlf ) Called one for each DLf records that should be categorised. The categoriser should add the extended fields directly to the $dlf hash reference. =cut sub categorise { croak "categorise() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 finalise( $config ) This method is called after all the DLF records were categorised. The $config parameter contains configuration data that was specified in the AnalysisJob for that analyser. To register configuration specification for you DlfCategoriser, you just need to define a configuration specification under the name I<analyser_name>_properties. This should be either a RecordSpec or ObjectSpec. The default implementation does nothing. =cut sub finalise { # Empty method } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfAnalyserProcess(3pm), Lire::DlfStore(3pm), Lire::PluginManager(3pm), Lire::DlfAnalyser(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: DlfCategoriser.pm,v 1.6 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Records.pm������������������������������������������������������������������0000644�0001750�0001750�00000015212�10460673255�013550� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Records; use strict; use base qw/ Lire::Aggregator /; use Carp; use POSIX qw/ strftime /; use Lire::DataTypes qw/ is_time_type is_quantity_type format_numeric_type /; use Lire::Utils qw/ check_param check_object_param tempfile /; =pod =head1 NAME Lire::Records - Base class for implementation of the records operator. =head1 SYNOPSIS use Lire::Records; =head1 DESCRIPTION This module is the base class for implementation of the records operator. The records operator isn't an aggregator nor a group operation. It only collects information on each DLF records which will be included in the report. =head1 CONSTRUCTOR =head2 new( %params ) Creates a new instance of a records operator. In addition to the normal report operator parameters, the records operator takes one additional parameter: =over =item fields A reference to an array containing the names of the DLF field that should be included in the report. =back =cut sub new { my ( $class, %args ) = @_; check_param( $args{'fields'}, 'fields' ); my $self = bless {}, $class; $self->SUPER::init( %args, 'op' => 'records' ); $self->fields( $args{'fields'} ); return $self; } #------------------------------------------------------------------------ # Method print( $fh, $prefix ) # # Implementaion of the method required by Lire::ReportOperator. sub print { my ($self,$fh, $prefix) = @_; $fh ||= \*STDOUT; $prefix ||= 0; my $pfx = " " x $prefix; print $fh $pfx, '<lire:records fields="', join( " ", @{$self->{'fields'}}), qq{"/>\n}; } =pod =head1 METHOD =head2 fields( [$new_fields] ) Returns a reference to an array containing the DLF field names that will be included in the report. You can use the $new_fields parameter to change that value. =cut sub fields { my ($self, $fields) = @_; if ( @_ == 2 ) { if ( defined $fields ) { check_object_param( $fields, 'fields', 'ARRAY' ); croak "fields cannot be empty\n" unless @$fields; foreach my $f ( @$fields ) { croak "$f isn't a defined field in the specfication's schemas" unless $self->report_spec()->has_field( $f ); } } else { croak "undefined fields\n"; } $self->{'fields'} = $fields; } $self->{'fields'}; } =pod =head2 ops() FIXME =cut sub ops { return [] if (@_ == 1); croak "records cannot contain any children"; } # Implements Lire::ReportOperator::name() sub name { return 'records:' . @{$_[0]->fields()}; } # Implements Lire::Aggregator::create_categorical_info sub create_categorical_info { my ( $self, $group_info ) = @_; foreach my $field ( @{ $self->fields() } ) { my $dlf_field = $self->report_spec()->field( $field ); $group_info->create_column_info( $field, 'categorical', $dlf_field->type, $dlf_field->label, ); } } # Overrides Lire::Aggregator::build_query sub build_query { my ($self, $query ) = @_; $self->SUPER::build_query( $query ); foreach my $field ( @{$self->{'fields'}} ) { $query->add_field( $field ); } $query->set_sort_spec( $self->report_spec()->schema()->timestamp_field()->name()) ; return; } sub create_entry { my ( $self, $group, $row ) = @_; my $entry = $group->create_entry(); for ( my $i=0; $i < @{$self->{'fields'}}; $i++ ) { my $value = $row->{$self->{'fields'}[$i]}; my $type = $group->group_info()->info_by_index( $i )->type(); if ( is_time_type( $type ) ) { $entry->add_name( strftime( '%Y-%m-%d %H:%M:%S', localtime $value ), $value ); } elsif ( is_quantity_type( $type ) ) { $entry->add_name( format_numeric_type( $value, $type ), $value ); } else { $entry->add_name( $value ); } } return $entry; } # Implements Lire::ReportOperator::init_merge() sub init_merge { my $self = $_[0]; # We use a temporary file to sort the DLF records according to # the group id we are using. $self->{'fh'} = tempfile(); $self->{'group_no'} = 0; return; } # Implements Lire::Aggregator::init_aggregator_data() sub init_aggregator_data { my ( $self ) = @_; my $value = $self->{'group_no'}++; return $value; } # Implements Lire::Aggregator::merge_aggregator_data() sub merge_aggregator_data { my ( $self, $group, $data ) = @_; croak "value should be of type Lire::Report::Group, not $group\n" unless UNIVERSAL::isa( $group, "Lire::Report::Group" ); my $fh = $self->{'fh'}; foreach my $e ( $group->entries() ) { my @fields = $e->data; print $fh join( " ", $data, map { $_->{'value'}} @fields ), "\n"; } } # Implements Lire::Aggregator::end_aggregator_data() sub end_aggregator_data { my ( $self, $data ) = @_; my $fh = $self->{'fh'}; print $fh $data, " LIRE_RECORDS_GROUP_DATA_END\n"; } # Implements Lire::Aggregator::create_group_entries() sub create_group_entries { my ( $self, $group, $data ) = @_; seek $self->{'fh'}, 0, 0 or croak "can't seek at the beginning of the temporary DLF file: $!\n"; my $dlf_fh = $self->{'fh'}; my $rx = qr/^$data /; while (<$dlf_fh>) { # Only keep the records matching the group id next unless /$rx/; chomp; my ( $id, @fields) = split / /, $_; # Check for end of group data marker last if $fields[0] eq 'LIRE_RECORDS_GROUP_DATA_END'; my $row = {}; foreach ( my $i=0; $i < @{$self->{'fields'}}; $i++ ) { $row->{ $self->{'fields'}[$i] } = $fields[$i]; } $self->create_entry( $group, $row ); } } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::Aggregate(3pm), Lire::ReportOperator(3pm), Lire::Group(3pm), Lire::Timegroup(3pm), Lire::Timeslot(3pm), Lire::Rangegroup(3pm) =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <wsourdeau@logerpotr.org> =head1 VERSION $Id: Records.pm,v 1.24 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/GroupField.pm���������������������������������������������������������������0000644�0001750�0001750�00000010703�10460673255�014207� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::GroupField; use strict; use Carp; use Lire::DataTypes qw/ check_xml_name is_quantity_type is_time_type /; use Lire::I18N qw/ dgettext dgettext_para /; use Lire::ReportSpec; use Lire::Utils qw/ check_param check_object_param /; =pod =head1 NAME Lire::GroupField - Class that implements the field element in report specifications. =head1 SYNOPSIS use Lire::GroupField; =head1 DESCRIPTION This module is used to represent the field elements that appears in the group aggregator element in report specifications. =head1 CONSTRUCTOR =head2 new( %params ) Creates a new Lire::GroupField object. It takes several parameters similar to Lire::ReportOperator. =over =item name The DLF field's name that this GroupField represents. This shouldn't be quantity or time field (other aggregators should be used for these). =item report_spec The report specification in which this the group field is added. =item label The column's label that should be used for this field. =back =cut sub new { my $proto = shift; my $class = ref( $proto) || $proto; my %params = @_; check_param( $params{'name'}, 'name', \&check_xml_name, "invalid 'name' parameter" ); check_object_param( $params{'report_spec'}, 'report_spec', "Lire::ReportSpec" ); croak "'$params{'name'}' field name is not defined in the specification's schemas" unless $params{'report_spec'}->has_field( $params{'name'} ); my $type = $params{'report_spec'}->field( $params{'name'} )->type(); croak "'$params{'name'}' field is of type '$type'" . ". Use Lire::Rangegroup for this type\n" if ( is_quantity_type( $type ) ); croak "'$params{'name'}' field is of type '$type'" . ". Use Lire::Timeslot or Lire::Timegroup for this type\n" if ( is_time_type( $type ) ); bless { 'name' => $params{'name'}, 'report_spec' => $params{'report_spec'}, 'i18n_domain' => $params{'i18n_domain'} || 'lire', 'label' => $params{'label'}, }, $class; } =pod =head2 name() Returns the DLF field name which we represent. =cut sub name { $_[0]{'name'}; } =pod =head2 label( [$new_label] ) Returns the label that should be used for the column we generate in the report. Default is to use the DLF field's label. It can be changed by passing a $new_label parameter. =cut sub label { my ( $self, $label ) = @_; $self->{'label'} = $label if @_ == 2; return dgettext( $self->{'i18n_domain'}, $self->{'label'} ? $self->{'label'} : $self->field()->label() ); } =pod =head2 field() Returns the DLF field which we represents as Lire::Field object. =cut sub field { return $_[0]{'report_spec'}->field( $_[0]{'name'} ); } # ------------------------------------------------------------------------ # Method print( $fh, $pfx ) # # The Lire::Group implementation delegates writing the field element # to us. sub print { my ($self, $fh, $pfx ) = @_; $pfx ||= 0; $fh ||= \*STDOUT; print $fh ' ' x $pfx; print $fh qq{<lire:field name="$self->{'name'}"}; print $fh qq{ label="$self->{'label'}"} if $self->{'label'}; print $fh "/>\n"; } # The Lire::ReportOperator create_categorical_info method is delegated # to us by Lire::Group implementation. sub create_categorical_info { my ( $self, $info ) = @_; $info->create_column_info( $self->name(), 'categorical', $self->field()->type(), $self->label() ); } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Group(3pm) =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <wolfgang@logreport.org> =head1 VERSION $Id: GroupField.pm,v 1.19 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������lire-2.1.1/all/lib/Lire/SimpleStat.pm���������������������������������������������������������������0000644�0001750�0001750�00000005541�10460672575�014244� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::SimpleStat; use strict; use base qw/ Lire::Aggregate /; use Carp; use Lire::DataTypes qw/ is_numeric_type format_numeric_type /; use Lire::Utils qw/ check_param /; =pod =head1 Lire::SimpleStat This class provides common implementation for the operator that implement common statistical operation on one DLF field. Subclasses don't have to override xml_attrs() nor the print() method. =head2 init( %params ) Subclasses should provide an additional parameter to the init() method. =over =item field The DLF field's name on which the statistic is computed. =back =cut sub init { my ( $self, %args ) = @_; $self->SUPER::init( %args ); check_param( $args{'field'}, 'field' ); $self->field( $args{'field'} ); return; } =pod =head2 field( [$new_field] ) Returns the name of the DLF field on which the statistic will be computed. If the $new_field is set, the field's attribute is changed to this new value. It must be a valid field name for the schema of the current report specification. =cut sub field { my ( $self, $field ) = @_; if ( @_ == 2 ) { check_param( $field, 'field', sub { return is_numeric_type( $self->report_spec()->field( $field )->type() ) }, "'field' parameter should be a numerical field" ); croak "'$field' isn't a defined field in the specification's schemas" unless $self->report_spec()->has_field( $field ); $self->{'field'} = $field; } return $self->{'field'}; } =pod =head2 dlf_field() Returns the field onto which we are computing a statistic as a Lire::Field object. =cut sub dlf_field { $_[0]->report_spec()->field( $_[0]->field() ); } # Implementats Lire::Aggregate::create_numerical_info sub create_numerical_info { my ( $self, $group_info ) = @_; $group_info->create_column_info( $self->name(), 'numerical', $self->dlf_field()->type(), $self->label() ); } # ------------------------------------------------------------------------ # Method xml_attrs() # # Implementation required by Lire::Aggregate sub xml_attrs { return qq{ field="$_[0]{'field'}"}; } # Implements Lire::Aggregate::sql_required_fields sub sql_required_fields { return [ $_[0]{'field'} ]; } # Implements Lire::Aggregate::create_value() sub create_value { my ( $self, $group, $row ) = @_; my %value; my $name = $self->name(); $value{'content'} = format_numeric_type( $row->{$name}, $self->dlf_field()->type() ); $value{'value'} = $row->{$name}; $self->set_missing_cases_value( $row, \%value ); return \%value; } # Implements Lire::Aggregate::data2dlf() sub data2dlf { my ($self, $data) = @_; my $name = $self->name(); return { "$name" => $$data, "_lr_${name}_mc" => $self->missing_cases( $data ), }; } 1; ���������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ReportSchedule.pm�����������������������������������������������������������0000644�0001750�0001750�00000017426�10460673255�015110� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ReportSchedule; use strict; use Carp; use Locale::TextDomain 'lire'; use Lire::DlfSchema; use Lire::ReportConfig; use Lire::FilterSpec; use Lire::FilterExpr; use Lire::Utils qw/ check_param check_object_param /; use Time::Local; use Lire::WeekCalculator; =pod =head1 NAME Lire::ReportSchedule - Object which reprents one periodical report generation. =head1 SYNOPSIS use Lire::ReportJob; use Lire::ReportSchedule; my $store = Lire::DlfStore->open( 'aStore' ); my $job = new Lire::ReportJob( "webServer" ); my $cfg = $store->get_report_config( 'daily_www_report' ); $job->add_schedule( new Lire::ReportSchedule( 'daily', $cfg ); $job->run( 'daily', $store ); =head1 DESCRIPTION Lire::ReportSchedule objects together with Lire::OutputJob objects make it possible to configure all kind of periodical report generation. Whereas the Lire::OutputJob is used to represent the formatting of one generated report, the Lire::ReportSchedule represents such a generation. It will be use to generate periodically one XML report in a DlfStore using one report configuration file. ReportSchedules grouped together in one ReportJob are assumed to generate compatible reports as far as merging is concerned. The idea is that previous reports generated in one ReportJob (according to different schedules) could be used as a data source when the DlfStore doesn't contain all the DLF records for the whole period. For example, if you don't keep one year of www DLF in your store, you could still generate an yearly report using the daily reports generated during the year. =head2 new( $period, $cfg ); Creates a new Lire::ReportSchedule that will generates an XML report using the Lire::ReportConfig $cfg on a $period period. $period should be one of 'hourly', 'daily', 'weekly', 'monthly' or 'yearly'. =cut sub new { my ( $class, $period, $cfg ) = @_; check_param( $period, 'period', qr/^(hourly|daily|weekly|monthly|yearly)$/, "'period' parameter should be one of 'hourly', 'daily', 'weekly', 'monthly' or 'yearly'" ); check_object_param( $cfg, 'cfg', 'Lire::ReportConfig' ); my $self = bless { '_period' => $period, '_cfg' => $cfg, '_output_jobs' => [], }, $class; return $self; } =pod =head2 period() Returns the period of this ReportSchedule. =cut sub period { $_[0]{'_period'} }; =pod =head2 period_range( [ $time ] ) Returns the starting and ending boundaries of the schedule period which includes $time. (Defaults to now). The ending boundary is excluded from the period and the starting boundary is included. =cut sub period_range { my ($self, $time) = @_; return Lire::Utils::period_range( $self->{'_period'}, $time || time() ); } =pod =head2 report_config( [ $new_cfg ] ) Returns (and optionally change) the Lire::ReportConfig object to use for this schedule. =cut sub report_config { my ( $self, $new_cfg ) = @_; if ( @_ == 2 ) { check_object_param( $new_cfg, 'new_cfg', 'Lire::ReportConfig' ); $self->{'_cfg'} = $new_cfg; } return $self->{'_cfg'}; } =pod =head2 init_report_config( [ $time ] ) Returns the Lire::ReportConfig object with filters set. A FilterSpec will have been added to each section of the ReportConfig object which will restrict the reporting on the period defined for the scedule. The boundaries of the period are determined according to $time which defaults to now. =cut sub init_report_config { my ( $self, $time ) = @_; $time ||= time(); my $cfg = $self->{'_cfg'}; my $range = $self->period_range( $time ); foreach my $sect ( $cfg->sections() ) { foreach my $spec ( $sect->reports() ) { my $field = '$' . $spec->schema()->timestamp_field()->name(); my $time_filter = new Lire::FilterExpr::And( 'container' => $spec, ); my $start = new Lire::FilterExpr::Ge( 'container' => $spec, 'arg1' => $field, 'arg2' => $range->[0] ); my $end = new Lire::FilterExpr::Lt( 'container' => $spec, 'arg1' => $field, 'arg2' => $range->[1] ); my $expr = [ $start, $end ]; push @$expr, $spec->filter_spec() if $spec->filter_spec(); $time_filter->expr( $expr ); $spec->filter_spec( $time_filter ); } } return $cfg; } =pod =head2 add_output_jobs( $job, ... ) Adds one or more Lire::OutputJob to the ReportSchedule object. =cut sub add_output_job { my ( $self, @jobs ) = @_; croak "missing one or more 'output_job' parameters" unless @jobs; foreach my $job ( @jobs ) { check_object_param( $job, 'output_job', 'Lire::OutputJob' ); push @{$self->{'_output_jobs'}}, $job; } return; } =pod =head2 output_jobs() Returns the Lire::OutputJobs related to this object. =cut sub output_jobs { return @{$_[0]{'_output_jobs'}}; } =pod =head2 run( $store, $report_job, [$time] ) Generate a XML report and save it in the $store Lire::DlfStore. The report will be generated either using the DlfStreams or previously generated reports. Preferences is giving to generating the report using the Dlf data For more details, consult the documentation of find_report_source() in Lire::DlfStore(3pm). The period for which the report will be generated is done using the $time parameter which defaults to now. For example, a 'daily' report will generate a report for the whole day (midnight-midnidht based on the day that $time represents). Once the report is generated, all registered OutputJob will be run with the new report. =cut sub run { my ( $self, $store, $report_job, $time ) = @_; my $source = $store->find_report_source( $report_job, $self, $time ); return if $source->{'source'} eq 'none'; my $cfg = $self->init_report_config( $time ); my $report; if ( $source->{'source'} eq 'merging' ) { $report = $cfg->merge_report_files( @{$source->{'reports'}} ); } else { $report = $cfg->generate_report( $store ); } $report->timespan_period( $self->period() ); $report->timespan_start( $source->{'start'} ); $report->timespan_end( $source->{'end'} ); my $report_file = $store->put_report( $report_job, $self, $report ); foreach my $job ( $self->output_jobs() ) { $job->run( $report_file, $time ); } return; } sub new_from_config { my ( $pkg, $dict ) = @_; $dict = $dict->Lire::Config::Dictionary::as_value(); my $sched = new Lire::ReportSchedule( $dict->{'period'}, $dict->{'report_config'}); $sched->add_output_job( @{$dict->{'output_jobs'}} ) if @{$dict->{'output_jobs'}}; return $sched; } 1; __END__ =pod =head1 SEE ALSO Lire::DlfStore(3pm) Lire::DlfConverter(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: ReportSchedule.pm,v 1.17 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/FilterExpr.pm���������������������������������������������������������������0000644�0001750�0001750�00000033627�10765035043�014240� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::FilterExpr; use strict; use Carp; use Lire::Utils qw/ check_param check_object_param /; sub new { my $class = shift; my %args = @_; check_object_param( $args{'container'}, 'container', 'Lire::XMLSpecContainer' ); my $self = bless { 'container' => $args{'container'}, }, $class; return $self; } sub _is_value_a_ref { my ( $self, $value ) = @_; return substr( $value, 0, 1 ) eq '$'; } sub _is_value_a_fieldref { my ( $self, $value ) = @_; return ( $self->_is_value_a_ref( $value ) && $self->{'container'}->has_field( $self->_refname_from_value( $value ) ) ); } sub _validate_ref_value { my ( $self, $value ) = @_; croak "value '$value' isn't a parameter or field reference" unless $self->_is_value_a_ref( $value ); my $name = $self->_refname_from_value( $value ); croak "'$name' isn't a defined parameter or field name" unless $self->{'container'}->has_param( $name ) || $self->{'container'}->has_field( $name ); } sub _refname_from_value { my ( $self, $value ) = @_; croak "value '$value' isn't a parameter or field reference" unless $self->_is_value_a_ref( $value ); return substr( $value, 1 ); } sub _validate_value { my ( $self, $value ) = @_; $self->_validate_ref_value( $value ) if $self->_is_value_a_ref( $value ); return 1; } sub print { croak ref($_[0]) . ": unimplemented abstract method"; } sub sql_expr { croak "Unimplemented sql_expr() in ", ref $_[0]; } sub sql_params { croak "Unimplemented sql_params() in ", ref $_[0]; } package Lire::FilterExpr::BinaryExpr; use base qw/Lire::FilterExpr/; use Carp; use Lire::Utils qw/ xml_encode sql_quote_name check_param /; sub new { my $self = shift()->SUPER::new( @_ ); my %args = @_; foreach my $para ( qw/ arg1 arg2 op sql_op / ) { check_param( $args{$para}, $para ); } $self->{'op'} = $args{'op'}; $self->{'sql_op'} = $args{'sql_op'}; $self->arg1( $args{'arg1'} ); $self->arg2( $args{'arg2'} ); return $self; } sub arg1 { my ($self, $arg1) = @_; if ( @_ == 2) { check_param( $arg1, 'arg1' ); $self->_validate_value( $arg1 ); $self->{'arg1'} = $arg1; } $self->{'arg1'}; } sub arg2 { my ($self, $arg2) = @_; if ( @_ == 2 ) { check_param( $arg2, 'arg2' ); $self->_validate_value( $arg2 ); $self->{'arg2'} = $arg2; } $self->{'arg2'}; } sub print { my ($self,$fh, $prefix) = @_; $fh ||= \*STDOUT; $prefix ||= 0; my $pfx = " " x $prefix; my $arg1 = xml_encode( $self->{'arg1'} ); my $arg2 = xml_encode( $self->{'arg2'} ); print $fh $pfx, qq{<lire:$self->{'op'} arg1="$arg1" arg2="$arg2"/>\n}; } sub sql_params { my $self = $_[0]; my @params = (); push @params, $self->{'container'}->resolve_param_ref( $self->{'arg1'} ), unless ( $self->_is_value_a_fieldref( $self->{'arg1'} ) ); push @params, $self->{'container'}->resolve_param_ref( $self->{'arg2'} ), unless ( $self->_is_value_a_fieldref( $self->{'arg2'} ) ); return \@params; } sub sql_expr { my $self = $_[0]; my $arg1 = ( $self->_is_value_a_fieldref( $self->{'arg1'} ) ) ? sql_quote_name($self->_refname_from_value( $self->{'arg1'})) : '?'; my $arg2 = ( $self->_is_value_a_fieldref( $self->{'arg2'} ) ) ? sql_quote_name($self->_refname_from_value( $self->{'arg2'})) : '?'; return "$arg1 $self->{'sql_op'} $arg2"; } package Lire::FilterExpr::Eq; use base qw/ Lire::FilterExpr::BinaryExpr /; sub new { return shift()->SUPER::new( @_ , 'op' => "eq", 'sql_op' => '=' ); } package Lire::FilterExpr::Ne; use base qw/ Lire::FilterExpr::BinaryExpr /; sub new { return shift()->SUPER::new( @_ , 'op' => "ne", 'sql_op' => '!=' ); } package Lire::FilterExpr::BinaryNumericExpr; use base qw/ Lire::FilterExpr::BinaryExpr /; use Carp; use Lire::DataTypes qw/ check_number is_numeric_type /; sub _validate_value { my ( $self, $value ) = @_; if ( $self->_is_value_a_ref( $value )) { $self->_validate_ref_value( $value ); my $name = $self->_refname_from_value( $value ); my $type; # Make sure it has the proper type if ( $self->{'container'}->has_param( $name ) ) { $type = $self->{'container'}->param( $name )->type; } else { $type = $self->{'container'}->field( $name )->type; } croak "variable must be a numeric type" unless is_numeric_type( $type ); } else { croak "literal isn't an int or number" unless check_number( $value ); } return; } package Lire::FilterExpr::Lt; use base qw/ Lire::FilterExpr::BinaryNumericExpr /; sub new { return shift()->SUPER::new( @_, 'op' => "lt", 'sql_op' => '<' ); } package Lire::FilterExpr::Le; use base qw/ Lire::FilterExpr::BinaryNumericExpr /; sub new { return shift()->SUPER::new( @_ , 'op' => "le", 'sql_op' => '<=' ); } package Lire::FilterExpr::Gt; use base qw/ Lire::FilterExpr::BinaryNumericExpr /; sub new { return shift()->SUPER::new( @_ , 'op' => "gt", 'sql_op' => '>' ); } package Lire::FilterExpr::Ge; use base qw/ Lire::FilterExpr::BinaryNumericExpr /; sub new { return shift()->SUPER::new( @_ , 'op' => "ge", 'sql_op' => '>=' ); } package Lire::FilterExpr::Match; use base qw/ Lire::FilterExpr /; use Carp; use Lire::DataTypes qw/ check_bool eval_bool /; use Lire::Utils qw/ xml_encode sql_quote_name check_param /; sub new { my $self = shift()->SUPER::new( @_ ); my %args = @_; foreach my $para ( qw/ value re / ) { check_param( $args{$para}, $para ); } $self->value( $args{'value'} ); $self->re( $args{'re'} ); $self->case_sensitive( $args{'case-sensitive'} || 0 ); return $self; } sub value { my ( $self, $value ) = @_; if ( @_ == 2) { check_param( $value, 'value' ); $self->_validate_value( $value ); $self->{'value'} = $value; } return $self->{'value'}; } sub re { my ( $self, $re ) = @_; if ( @_ == 2 ) { check_param( $re, 're' ); if ( $self->_is_value_a_ref( $re ) ) { my $name = $self->_refname_from_value( $re ); $self->_validate_ref_value( $re ); croak "re parameter cannot be a reference to a DLF field: $re" unless $self->{'container'}->has_param( $name ); } $self->{'re'} = $re; } return $self->{'re'}; } sub case_sensitive { my ( $self, $cs ) = @_; if ( @_ == 2 ) { check_param( $cs, 'cs' ); croak "invalid bool value : $cs" unless check_bool( $cs ); $self->{'case_sensitive'} = $cs; } return eval_bool( $self->{'case_sensitive'} ); } sub print { my ($self,$fh, $prefix) = @_; $fh ||= \*STDOUT; $prefix ||= 0; my $pfx = " " x $prefix; my $value = xml_encode( $self->{'value'} ); my $re = xml_encode( $self->{'re'} ); print $fh $pfx, qq{<lire:match value="$value" re="$re"}; if (defined $self->{'case_sensitive'}) { print $fh qq{ case-sensitive="$self->{'case_sensitive'}"}; } print $fh "/>\n"; return; } sub sql_params { my $self = $_[0]; my @params = (); push @params, $self->{'container'}->resolve_param_ref( $self->{'value' } ) unless ( $self->_is_value_a_fieldref( $self->{'value' } ) ); push @params, $self->{'container'}->resolve_param_ref( $self->{'re' } ); return \@params; } sub sql_expr { my $self = $_[0]; my $val; if ( $self->_is_value_a_fieldref( $self->{'value' } ) ) { $val = sql_quote_name( $self->_refname_from_value($self->{'value' })); } else { $val = '?'; } return 'lr_match(' . $val . ',?,' . $self->case_sensitive() . ')'; } package Lire::FilterExpr::Value; use base qw/ Lire::FilterExpr /; use Lire::Utils qw/ xml_encode sql_quote_name check_param /; use Carp; sub new { my $self = shift()->SUPER::new( @_ ); my %args = @_; check_param( $args{'value'}, 'value' ); $self->value( $args{'value'} ); return $self; } sub value { my ( $self, $value ) = @_; if ( @_ == 2 ) { check_param( $value, 'value' ); $self->_validate_value( $value ); $self->{'value'} = $value; } $self->{'value'}; } sub print { my ($self,$fh, $prefix) = @_; $fh ||= \*STDOUT; $prefix ||= 0; my $pfx = " " x $prefix; my $value = xml_encode( $self->{'value'} ); print $fh $pfx, qq{<lire:value value="$value"/>\n}; } sub sql_params { my $self = $_[0]; unless ( $self->_is_value_a_fieldref( $self->{'value' } ) ) { my $val = $self->{'container'}->resolve_param_ref ( $self->{'value' }); return [ ( $val ) x 3 ]; } else { return []; } } sub sql_expr { my $self = $_[0]; if ( $self->_is_value_a_fieldref( $self->{'value' } ) ) { my $f = sql_quote_name( $self->_refname_from_value($self->{'value' })); return $f . ' IS NOT NULL AND ' . $f . ' != 0 AND LENGTH(' . $f . ') > 0'; } else { return '? IS NOT NULL AND ? != 0 AND LENGTH(?) > 0'; } } package Lire::FilterExpr::DlfSource; use base qw/ Lire::FilterExpr /; use Lire::Utils qw/ sql_quote_name check_param /; use Carp; sub new { my $self = shift()->SUPER::new( @_ ); my %args = @_; check_param( $args{'value'}, 'value' ); $self->value( $args{'value'} ); return $self; } sub value { my ( $self, $value ) = @_; if ( @_ == 2 ) { check_param( $value, 'value' ); $self->_validate_value( $value ); $self->{'value'} = $value; } $self->{'value'}; } sub print { croak "Cannot print a Lire::FilterExpr::DlfSource"; } sub sql_params { my $self = $_[0]; unless ( $self->_is_value_a_fieldref( $self->{'value' } ) ) { return [ $self->{'container'}->resolve_param_ref ( $self->{'value' }) ]; } else { return [ $self->{'value'} ]; } } sub sql_expr { my $self = $_[0]; return $self->{'container'}->schema()->sql_table() . ".dlf_source" . " = ?"; } package Lire::FilterExpr::Not; use base qw/ Lire::FilterExpr /; use Carp; use Lire::Utils qw/ check_object_param /; sub expr { my ( $self, $expr ) = @_; if ( @_ == 2 ) { check_object_param( $expr, 'expr', 'Lire::FilterExpr' ); $self->{'expr'} = $expr; } return $self->{'expr'}; } sub print { my ($self,$fh, $prefix) = @_; $fh ||= \*STDOUT; $prefix ||= 0; croak "invalid not expression: missing child" unless defined $self->{'expr'}; my $pfx = " " x $prefix; print $fh $pfx, "<lire:not>\n"; $self->{'expr'}->print( $fh, $prefix + 1 ); print $fh $pfx, "</lire:not>\n"; } sub sql_params { my $self = $_[0]; return $self->{'expr'}->sql_params(); } sub sql_expr { my $self = $_[0]; return 'NOT (' . $self->{'expr'}->sql_expr() . ')'; } package Lire::FilterExpr::And; use base qw/ Lire::FilterExpr /; use Carp; use Lire::Utils qw/ check_object_param /; sub expr { my ( $self, $expr ) = @_; if (@_ == 2 ) { check_object_param( $expr, 'expr', 'ARRAY' ); croak "'expr' must contains at least one expression" unless @$expr; foreach my $e ( @$expr) { check_object_param( $e, 'e', 'Lire::FilterExpr' ); } $self->{'expr'} = $expr; } return $self->{'expr'}; } sub print { my ($self,$fh, $prefix) = @_; $fh ||= \*STDOUT; $prefix ||= 0; croak "invalid and expression: missing children" unless ref $self->{'expr'} eq 'ARRAY' && @{$self->{'expr'}}; my $pfx = " " x $prefix; print $fh $pfx, "<lire:and>\n"; foreach my $e ( @{$self->{'expr'}}) { $e->print( $fh, $prefix + 1 ); } print $fh $pfx, "</lire:and>\n"; return; } sub sql_params { my $self = $_[0]; return [ map { @{$_->sql_params()} } @{$self->{'expr'}} ]; } sub sql_expr { my $self = $_[0]; return join (' AND ', map {'(' . $_->sql_expr() . ')'} @{$self->{'expr'}}); } package Lire::FilterExpr::Or; use base qw/ Lire::FilterExpr /; use Carp; use Lire::Utils qw/ check_object_param /; sub expr { my ( $self, $expr ) = @_; if ( @_ == 2 ) { check_object_param( $expr, 'expr', 'ARRAY' ); croak "'expr' must contain at leat one expression" unless @$expr; foreach my $e ( @$expr) { croak "$e isn't an expression" unless UNIVERSAL::isa( $e, 'Lire::FilterExpr' ); } $self->{'expr'} = $expr; } $self->{'expr'}; } sub print { my ($self,$fh, $prefix) = @_; $fh ||= \*STDOUT; $prefix ||= 0; croak "invalid or expression: missing children" unless ref $self->{'expr'} eq 'ARRAY' && @{$self->{'expr'}}; my $pfx = " " x $prefix; print $fh $pfx, "<lire:or>\n"; foreach my $e ( @{$self->{'expr'}}) { $e->print( $fh, $prefix + 1 ); } print $fh $pfx, "</lire:or>\n"; } sub sql_params { my $self = $_[0]; return [ map { @{$_->sql_params()} } @{$self->{'expr'}} ]; } sub sql_expr { my $self = $_[0]; return join (' OR ', map {'(' . $_->sql_expr() . ')'} @{$self->{'expr'}}); } # keep perl happy 1; __END__ =pod =head1 NAME Lire::FilterExpr - Lire Filter expression =head1 SYNOPSIS use Lire::FilterExpr =head1 DESCRIPTION FIXME =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: FilterExpr.pm,v 1.33 2008/03/09 19:27:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ���������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/I18N.pm���������������������������������������������������������������������0000644�0001750�0001750�00000010156�10765035043�012623� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::I18N; use strict; use base qw/ Exporter /; use Carp; use Locale::Messages qw/ bindtextdomain /; use vars qw/ $USE_ENCODING @EXPORT_OK /; BEGIN { @EXPORT_OK = qw/ set_fh_encoding ensure_utf8 local_codeset ensure_local_codeset mark_unicode bindtextdomain dgettext dgettext_para /; eval { use File::Temp qw/tempfile/; my $fh = tempfile(); binmode( $fh, ":utf8" ) or die( "encoding layer unavailable: $!" ); require Encode; require I18N::Langinfo; Encode->import( qw/ encode is_utf8 _utf8_on resolve_alias / ); }; $USE_ENCODING = ! $@; } use Lire::Utils qw/ check_param /; =pod =head1 NAME Lire::I18N - Lire internationalisation class =head1 SYNOPSIS use Lire::I18N =head1 DESCRIPTION FIXME =cut sub set_fh_encoding { my ( $fh, $encoding ) = @_; check_param( $fh, 'fh' ); check_param( $encoding, 'encoding' ); return unless $USE_ENCODING; return unless resolve_alias( $encoding ) ne local_codeset(); binmode( $fh, ":encoding($encoding)" ) or croak "error setting encoding on FH: $!"; } sub ensure_utf8 { my $string = $_[0]; return undef unless defined $string; return escape_8bits( $_[0] ) unless $USE_ENCODING; if ( is_utf8( $string ) ) { return $string; } elsif( local_codeset() eq 'utf8' ) { _utf8_on( $string ); return $string; } else{ my $rs = encode( 'utf8', $string ); _utf8_on( $rs ); return $rs; } } sub local_codeset { my $string = $_[0]; my $codeset = eval { resolve_alias( I18N::Langinfo::langinfo( I18N::Langinfo::CODESET() ) ) }; return $codeset ? $codeset : 'ISO-8859-1'; } sub ensure_local_codeset { my $string = $_[0]; return undef unless defined $string; return $string unless $USE_ENCODING && is_utf8( $string ); return encode( local_codeset(), $string ); } sub escape_8bits { my $string = $_[0]; return undef unless defined $string; $string =~ tr/[\x80-\xFF]/?/; # String may be UTF-8 encoded and thus # contain pointcodes above 255 # \x{FFFE} and \x{FFFF} are invalid UTF-8 # characters use utf8; # Required for 5.6 $string =~ s/[\x{100}-\x{FFFD}]/?/g; return $string; } sub mark_unicode { my $string = $_[0]; return undef unless defined $string; return $string unless $USE_ENCODING; _utf8_on( $string ) unless is_utf8( $string ); return $string; } sub dgettext { my ( $domain, $msgid ) = @_; check_param( $domain, 'domain' ); return Locale::Messages::dgettext( $domain, ensure_local_codeset( $msgid ) ); } sub dgettext_para { my ( $domain, $msgid ) = @_; check_param( $domain, 'domain' ); return undef unless defined $msgid; my ($para_start) = $msgid =~ m{^(\s*<para>\s*)}; $para_start ||= ''; my ($para_end) = $msgid =~ m{(\s*</para>\s*)$}; $para_end ||= ''; my $end = -length( $para_end ) || length( $msgid ); my $string = substr( $msgid, length( $para_start ), $end ); return $para_start . dgettext( $domain, $string ) . $para_end; } # keep perl happy 1; __END__ =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <wsourdeau@logreport.org> =head1 VERSION $Id: I18N.pm,v 1.26 2008/03/09 19:27:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ReportConfig.pm�������������������������������������������������������������0000644�0001750�0001750�00000054243�10460673255�014557� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ReportConfig; use strict; use Text::ParseWords qw/ shellwords /; use Lire::DlfSchema; use Lire::ReportSpec; use Lire::FilterSpec; use Lire::FilterExpr; use Lire::I18N qw/ set_fh_encoding /; use Lire::Report; use Lire::ReportSection; use Lire::DlfAnalyserProcess; use Lire::ReportParser::ReportBuilder; use Lire::Utils qw/check_param check_object_param /; use Lire::Config; use Lire::Config::ReportSpec; use Lire::Config::SpecParser; use Lire::Error qw/ directory_not_readable /; use Carp; =pod =head1 NAME Lire::ReportConfig - API to the report configuration file =head1 SYNOPSIS use Lire::ReportConfig; my $templates = Lire::ReportConfig->templates(); if ( Lire::ReportConfig->has_template( 'www_default' ) ) { my $report_cfg = Lire::ReportConfig->template( 'www_default' )->as_value(); my $report = $report_cfg->generate_report( $report ); } =head1 DESCRIPTION This class represents report configurations. Report configurations are stored as an XML configuration using the Lire::Report::ReportSpec configuration type. =head1 TEMPLATES Template reports are configuration specification files found in the directories specified by the 'lr_templates_path' configuration variable. =head2 templates() Returns an array reference containing the names of all defined templates. =cut our %TEMPLATES = (); sub templates { my $self = $_[0]; my %templates = map { $_ => 1} keys %TEMPLATES; foreach my $dir ( @{ Lire::Config->get( 'lr_templates_path' ) } ) { opendir my $dh, $dir or die directory_not_readable( $dir ), "\n"; foreach my $name ( readdir $dh ) { next unless $name =~ /^([-.\w]+)\.xml$/; $templates{$1} = 1; } closedir $dh; } return [ keys %templates ]; } sub _find_template_file { my ( $self, $name ) = @_; foreach my $dir ( @{ Lire::Config->get( 'lr_templates_path' ) } ) { return "$dir/$name.xml" if -f "$dir/$name.xml"; } return undef; } =pod =head2 has_template( $name ) Returns true if there is a template named $name available. =cut sub has_template { my ( $self, $name ) = @_; check_param( $name, 'name' ); return 1 if exists $TEMPLATES{$name}; return defined $self->_find_template_file( $name ); } =pod =head2 template( $name ) Returns a Lire::Config::Object defining the template ReportConfig named $name. Its spec() method would return a Lire::Config::ReportSpec object and its as_value() method would instantiate a Lire::ReportConfig object. =cut sub template { my ( $self, $name ) = @_; check_param( $name, 'name' ); return $TEMPLATES{$name} if exists $TEMPLATES{$name}; my $file = $self->_find_template_file( $name ); croak "no template named '$name' found in lr_templates_path" unless defined $file; my $parser = new Lire::Config::SpecParser(); my $spec = $parser->parsefile( $file ); croak "error in template file '$file', there is no component named '$name'" unless $spec->has_component( $name ); return $TEMPLATES{$name} = $spec->get( $name )->instance(); } =pod =head1 CONSTRUCTORS =head2 new() This creates a new empty Lire::ReportConfig object. The created report configuration object doesn't contain any section, report or filter specifications. =cut sub new { return bless { '_sections' => [], '_encoding' => undef, '_filename' => undef, '_title' => undef, }, shift; } =pod =head2 new_from_file( $superservice, $report_cfg ) This will create a new report configuration object for the $superservice superservice based on the report configuration file $report_cfg. =cut sub new_from_file { my ( $class, $superservice, $report_cfg ) = @_; check_param( $superservice, 'superservice', sub { Lire::DlfSchema->has_superservice( $_[0] ) }, 'invalid superservice' ); my $self = $class->new(); $self->_load_from_file( $superservice, $report_cfg ); return $self; } sub new_from_config { my ( $self, $value ) = @_; my $def = $value->Lire::Config::Dictionary::as_value(); my $cfg = new Lire::ReportConfig(); $cfg->title( $def->{'title'} ) if $def->{'title'}; foreach my $section ( @{$def->{'sections'}} ) { $cfg->add_section( $section ); } return $cfg; } =pod =head1 OBJECT METHODS =pod =head2 filename( [ $new_filename ] ) Returns (and optionanly changes) the filename from which this ReportConfig was loaded. It will return undef if the ReportConfig wasn't loaded from a file. =cut sub filename { $_[0]{'_filename'} = $_[1] if @_ == 2; return $_[0]{'_filename'}; } =pod =head2 title( [ $new_title ] ) Returns (and optionnally changes) the title that will be assigned to the report. =cut sub title { my ( $self, $new_title ) = @_; $self->{'_title'} = $new_title if @_ == 2; return $self->{'_title'}; } sub _load_from_file { my ( $self,$superservice, $report_cfg ) = @_; # Reset the sections $self->{'_sections'} = []; # Format of the configuration file is # ((=section <title>) # (|filter_id <param>)* # (report_id <param>))*)+ $self->{'_curr_section'} = undef; $self->{'_id_cache'} = {}; # Load the report configuration file open my $fh, $report_cfg or die "can't open report configuration file $report_cfg: $!\n"; $self->{'_fh'} = $fh; my $line; while ( defined( $line = <$fh> ) ) { next if $line =~ /^\s*#/; # Skip comments next if $line =~ /^\s*$/; # Skip blank lines chomp $line; my $first_char = substr( $line, 0, 1 ); if ( $first_char eq '=' ) { if ( $line =~ /^=encoding/ ) { $self->_parse_encoding_line( $line ); } elsif ( $line =~ /^=section/ ) { $self->_parse_section_line( $superservice, $line ); } else { warn "Unknown directive at line $.: $line\n"; } } elsif ( $first_char eq '|' ) { $self->_parse_filter_line( $superservice, $line ); } else { $self->_parse_report_line( $superservice, $line ); } } close $fh; delete $self->{'_fh'}; delete $self->{'_curr_section'}; delete $self->{'_id_cache'}; $self->{'_filename'} = $report_cfg; return; } sub _parse_encoding_line { my ( $self, $line ) = @_; die "'encoding' directive requires perl >= 5.8.0, at line $.\n" unless $Lire::I18N::USE_ENCODING; die "'encoding' directive must be the first directive, at line $.\n" if ( defined $self->{'_curr_section'} ); die "only one 'encoding' directive allowed, at line $.\n" if ( defined $self->{'_encoding'} ); $line =~ /^=encoding\s+([-\w.]+)$/; die "invalid 'encoding' directive, at line $.\n" unless ( defined $1 ); $self->{'_encoding'} = $1; set_fh_encoding( $self->{'_fh'}, $1 ); return; } sub _parse_section_line { my ( $self, $superservice, $line ) = @_; unless ( $line =~ /^=section (.*)$/ ) { warn "invalid section directive at line $.: $line"; return; } $self->{'_curr_section'} = new Lire::ReportSection( $superservice, $1 ); $self->add_section( $self->{'_curr_section'} ); return; } sub _parse_filter_line { my ( $self, $superservice, $line ) = @_; my ( $id, $params ) = _parse_param_line( substr( $line, 1 ) ); eval { die "filter specification before any =section directive\n" unless $self->{'_curr_section'}; die"filter specification should come before report specifications\n" if $self->{'_curr_section'}->reports(); my $spec = Lire::FilterSpec->load( $superservice, $id ); while ( my ($name, $value) = each %$params ) { $spec->param( $name )->value( $value ); } $self->{'_curr_section'}->add_filter( $spec ); }; if ( $@ ) { warn( "error at line $.: $@\n" ); warn( "Omitting filter $id defined at line $.\n" ); } return; } sub _parse_report_line { my ( $self, $superservice, $line ) = @_; my ( $id, $params ) = _parse_param_line( $line ); eval { die "report specification before any =section directive\n" unless $self->{'_curr_section'}; my $report_spec = Lire::ReportSpec->load( $superservice, $id ); while ( my ($name, $value) = each %$params ) { $report_spec->param( $name )->value( $value ); } $self->{'_id_cache'}{$id} ||= 0; $report_spec->subreport_id( $id . "." . $self->{'_id_cache'}{$id}++ ); $self->{'_curr_section'}->add_report( $report_spec ); }; if ( $@ ) { warn( "error at line $.: $@\n" ); warn( "Omitting report $id defined at line $.\n" ); } return; } sub _parse_param_line { my ( $id, @p ) = shellwords( $_[0] ); my %params = (); foreach my $param_str ( @p ) { my ( $param, $value ) = $param_str =~ /^([-.\w]+)=(.*)$/; unless ( defined $param ) { warn( "error parsing parameter $param_str at line $.. Ignoring parameter.\n" ); next; } $value = "" unless defined $value; $params{$param} = $value; } return ( $id, \%params ); } sub create_param_line { my ( $id, $spec ) = @_; my @line = ( $id ); foreach my $name ( $spec->param_names() ) { my $value = $spec->param( $name )->value(); $value =~ s/\\/\\\\/g; # Escape backslashes $value =~ s/"/\\"/g; # and double quotes push @line, $name . '="' . $value . '"'; } return join( " ", @line ); } =pod =head2 schemas() Returns an array reference containing the name of the schemas used in this report. =cut sub schemas { my $self = $_[0]; my %schemas = (); foreach my $section ( $self->sections() ) { foreach my $report ( $section->reports() ) { foreach my $schema ( @{$report->schemas()} ) { $schemas{$schema} = 1 } } } return [ keys %schemas ]; } =pod =head2 sections() Return's this report configuration's sections as an array of Lire::Section objects. =cut sub sections { my ( $self ) = @_; return @{$self->{'_sections'}}; } =pod =head2 add_section( $section ) Adds a section to this report configuration. The $section parameter should be a Lire::ReportSection object. =cut sub add_section { my ( $self, $section ) = @_; check_object_param( $section, 'section', 'Lire::ReportSection' ); push @{$self->{'_sections'}}, $section; return; } =pod =head2 merge_filters() Calling this method will make sure that all report specifications take into account their section's filter specification. This method will modify all report specifications. After this their object representation won't be identical to the one in the XML report specification. =cut sub merge_filters { my ( $self ) = @_; foreach my $section ( $self->sections() ) { my @filters = map { $_->filter_spec() } $section->filters(); my @reports = $section->reports(); foreach my $r ( @reports ) { if ( @filters ) { my $expr; if ( $r->filter_spec || @filters > 1) { $expr = new Lire::FilterExpr::And( 'container' => $r ); if ( $r->filter_spec ) { $expr->expr( [ @filters, $r->filter_spec ] ); } else { $expr->expr( [@filters] ); } } else { $expr = $filters[0]; } $r->filter_spec( $expr ); } } } return; } =pod =head2 print( [$fh] ) Prints the report configuration on the $fh filehandle. If the $fh parameter is omitted, the report configuration will be printed on STDOUT. =cut sub print { my ( $self, $fh ) = @_; $fh ||= \*STDOUT; if ( defined $self->{'_encoding'} ) { set_fh_encoding( $fh, $self->{'_encoding'} ); print $fh "=encoding ", $self->{'_encoding'}, "\n\n"; } foreach my $section ( $self->sections() ) { print $fh "=section ", $section->title(), "\n"; foreach my $filter ( $section->filters() ) { print $fh create_param_line( "|" . $filter->id(), $filter ), "\n"; } foreach my $report ( $section->reports() ) { print $fh create_param_line( $report->id(), $report ), "\n"; } # Empty line print $fh "\n" } } # Used by lr_report_cfg2xml to convert file-based # report configuration to the new XML format. sub as_config_value { my ( $self, $name ) = @_; my %filters_id = (); check_param( $name, 'name' ); my $spec = new Lire::Config::ReportSpec( 'name' => $name ); my $cfg = $spec->instance(); $cfg->get( 'id' )->set( $name ); foreach my $section ( @{$self->{'_sections'}} ) { my $sect_cfg = $spec->get( 'sections' )->get( 'section' )->instance(); $cfg->get( 'sections' )->append( $sect_cfg ); $sect_cfg->get( 'superservice' )->set( $section->superservice() ); $sect_cfg->get( 'title' )->set( $section->title() ); foreach my $filter ( $section->filters() ) { my $type = $filter->id(); my $id = $filter->superservice() . ':' . $type; my $filter_cfg = $sect_cfg->spec()->get( 'filters' )->get( $id )->instance(); $filters_id{$type} ||= 0; $filter_cfg->get( 'id' )->set( $type . '.' . $filters_id{$type}++); foreach my $name ( $filter->param_names() ) { $filter_cfg->get( $name )->set( $filter->param( $name )->value() ); } $sect_cfg->get( 'filters' )->append( $filter_cfg ); } foreach my $report ( $section->reports() ) { my $id = $report->superservice() . ':' . $report->id(); my $report_cfg = $sect_cfg->spec()->get( 'specs' )->get( $id )->instance(); $report_cfg->get( 'id' )->set( $report->subreport_id() ); foreach my $name ( $report->param_names() ) { $report_cfg->get( $name )->set( $report->param( $name )->value() ); } $sect_cfg->get( 'specs' )->append( $report_cfg ); } } return $cfg; } =pod =head2 create_report( $timespan_start, $timespan_end ) Returns a Lire::Report object based on this report's configuration file. The $timespan_start and $timespan_end attribute will be used to initiate the Report object. Used when generating an XML report from a DLF source, and when merging XML reports. The real job is delegated to Lire::ReportSection::create_report_section(). =cut sub create_report { my ( $self, $start, $end) = @_; my $report = new Lire::Report(); $report->timespan_start( $start ); $report->timespan_end( $end ); $report->title( $self->{'_title'} ) if defined $self->{'_title'}; foreach my $s ( $self->sections() ) { $s->create_report_section( $report ); } return $report; } =pod =head2 create_analyser_streams( $store ) This method will make sure that a DlfStream is available in the Lire::DlfStore $store for each schema used by this report configuration. The stream will be created by running the first analyser which is able to generate the schema using exising streams. =cut sub create_analyser_streams { my ($self, $store ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); foreach my $schema ( @{$self->schemas()} ) { $self->_create_dlf_stream( $store, $schema ) unless $store->has_dlf_stream( $schema ); } return; } sub _create_dlf_stream { my ( $self, $store, $schema_id ) = @_; my $schema = Lire::DlfSchema::load_schema( $schema_id ); my $analysers = Lire::PluginManager->analysers_by_dst( $schema_id ); unless ( @$analysers ){ warn( "no analysers available to create '", $schema_id, "' stream" ); return; } my $analyser = $analysers->[0]->name(); my $cfg = Lire::Config->config_spec()->has_component( "${analyser}_properties") && Lire::Config->get( "${analyser}_properties" ) || ''; my $process = new Lire::DlfAnalyserProcess( $store, $analyser, $cfg ); $process->run_analysis_job(); return; } =pod =head2 generate_report( $store ) Generates a Lire::Report from this report configuration. The report is computed using the streams in the Lire::DlfStore $store. =cut sub generate_report { my ( $self, $store ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); # Merge the sections' filter specifications $self->merge_filters(); my ( $start, $end ) = $self->_find_dlf_time( $store ); foreach my $section ( @{$self->{'_sections'}} ) { foreach my $report_spec ( $section->reports() ) { my $r = $report_spec->subreport_id(); unless ( $store->has_dlf_stream( $report_spec->schema()->id()) ) { warn( "report '$r' will be skipped because of unavailable input"); $report_spec->mark_missing( "unavailable input" ); next; } eval { $report_spec->set_store( $store ); }; if ( $@ ) { warn( $@ ); $report_spec->mark_missing( 'set_store() failed: $@' ); } } } return $self->create_report( $start, $end ); } sub _find_dlf_time { my ( $self, $store ) = @_; my $dlf_stream = $store->open_dlf_stream( $self->{'_sections'}[0]->superservice(), "r" ); my $start = $dlf_stream->start_time(); my $end = $dlf_stream->end_time(); $dlf_stream->close(); return ( $start, $end ); } # Merging =pod =head2 merge_report_files( @report_files ) Generate a new Lire::Report based on this report configuration by merging XML reports. Every report spec contained in the configuration will be the result of the merging of all the subreports having the same id. =cut sub merge_report_files { my ( $self, @files ) = @_; $self->_init_merge(); my $non_missing = {}; my $parser = new Lire::ReportParser::ReportBuilder(); foreach my $r ( @files ) { my $report = eval { $parser->parsefile( $r ) }; if ( $@ ) { warn( "error parsing XML report $r: $@. Skipping" ); next; } $self->_update_merged_timespan( $report ); $self->_merge_report( $report, $non_missing ); $report->delete(); } $self->_end_merge( $non_missing ); return $self->create_report( $self->{'report_start'}, $self->{'report_end'} ); } sub _init_merge { my $self = $_[0]; foreach my $section ( $self->sections() ) { foreach my $spec ( $section->reports() ) { my $id = $spec->subreport_id(); eval { $spec->calc_spec()->init_merge() }; if ( $@ ) { warn( "$@\nreport '$id' will be skipped" ); $spec->mark_missing( "init_merge() failed: $@" ); } } } } sub _end_merge { my ( $self, $non_missing ) = @_; foreach my $section ( $self->sections() ) { foreach my $spec ( $section->reports() ) { my $id = $spec->subreport_id(); eval { $spec->calc_spec()->end_merge() }; if ( $@ ) { warn( "$@\nreport '$id' will be skipped" ); $spec->mark_missing( "end_merge() failed: $@" ); } # Mark missing, if it was also missing in all reports $spec->mark_missing( "missing in all merged reports" ) unless $non_missing->{$id}; } } } sub _merge_report { my ( $self, $report, $non_missing ) = @_; foreach my $section ( $self->sections() ) { foreach my $spec ( $section->reports() ) { # Skip failed reports next if $spec->is_missing(); my $id = $spec->subreport_id(); die "assertion failed: missing subreport_id on specification ", $spec->id() unless defined $id; # Find the matching subreport in this report my $subreport = $report->subreport_by_id( $id ); unless ( $subreport ) { warn( "no subreport id '$id' in this report" ); next; } eval { $spec->calc_spec()->merge_subreport( $subreport ); }; if ($@) { warn( $@ ); warn( "Merge of '$id' failed" ); next; } $non_missing->{$id} = 1; } } } sub _update_merged_timespan { my ( $self, $report ) = @_; # Start and end of merged report is the union of the range of # all the reports # timespan_start and timespan_end are in seconds since epoch unless ( defined $self->{'report_start'} ) { $self->{'report_start'} = $report->timespan_start(); $self->{'report_end'} = $report->timespan_end(); } # It is possible for a report to have # an unknown period if ( $report->timespan_start() ) { $self->{'report_start'} = $report->timespan_start() if $report->timespan_start() < $self->{'report_start'}; $self->{'report_end'} = $report->timespan_end() if $report->timespan_end() > $self->{'report_end'}; } } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::ReportSection(3pm), Lire::ReportSpec(3pm), Lire::FilterSpec(3pm) Lire::Report(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: ReportConfig.pm,v 1.38 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/XMLSpecContainer.pm���������������������������������������������������������0000644�0001750�0001750�00000040724�10460673256�015274� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::XMLSpecContainer; use strict; use Lire::DlfSchema; use Lire::DataTypes qw/ check_superservice check_xml_name /; use Lire::Utils qw/ xml_encode check_param check_object_param /; use Lire::I18N qw/ dgettext dgettext_para /; use Lire::Config::XMLSpecListSpec; use Lire::XMLSpecParser; use Carp; =pod =head1 NAME Lire::XMLSpecContainer - Base clase for XML report and filter specifications =head1 SYNOPSIS use base qw/Lire::XMLSpecContainer/; =head1 DESCRIPTION This is the base class for Lire::ReportSpec and Lire::FilterSpec which are XML specifications used to compute reports. This man page document the attributes common to both type of specification. =cut sub load { my ( $self, $super, $id ) = @_; check_param( $super, 'super', \&check_superservice ); check_param( $id, 'id', \&check_xml_name ); my $file = $self->file_from_id( $super, $id ); my $parser = new Lire::XMLSpecParser(); my $spec = eval { $parser->parsefile( $file ) }; croak "error while parsing XML specification $id: $@" if $@; # Some sanity checks croak "$file has superservice '", $spec->superservice(), "' when it should be '", $super, "'\n" unless $spec->superservice() eq $super; croak "$file has id '", $spec->id(), "' when it should be '", $id, "'\n" unless $spec->id() eq $id; return $spec; } sub new { return bless { 'params' => {}, '_joined_schemas' => [], }, shift; } =pod =head2 id( [ $new_id ] ) Returns the type id of this specification. It $new_id is set, it will change the id of the specification. =cut sub id { my ( $self, $id ) = @_; if ( defined $id ) { check_param( $id, 'id', \&check_xml_name ); $self->{'id'} = $id; } return $self->{'id'}; } =pod =head2 superservice( [ $new_superservice ] ) Returns the superservice (aka base DLF schema) used by this specification. It $new_superservice is set, it will change the superservice of the specification. =cut sub superservice { my ( $self, $superservice ) = @_; if ( defined $superservice ) { check_param( $superservice, 'superservice', \&check_superservice ); # Schema can't be valid if we switch superservice delete $self->{'schema'} if defined $self->{'superservice'} && $self->{'superservice'} ne $superservice; $self->{'superservice'} = $superservice; } return $self->{'superservice'}; } =pod =head2 schema( [ $new_schema ] ) Returns the Lire::DLfSchema object used by this specification. This can be the superservice or any of its Lire::ExtendedSchema or Lire::DerivedSchema. If $new_schema is a string, the specification's schema will be changed to that schema. If $new_schema is undef, the base DlfSchema (aka superservice) will be used. =cut sub schema { my ( $self, $schema ) = @_; if ( @_ == 2 ) { if (defined $schema) { my ( $super ) = $schema =~ /^(\w+)-/; croak "invalid schema identifier: $schema" unless $super; croak "superservice of schema isn't correct: $super != $self->{'superservice'}" unless $super eq $self->{'superservice'}; $self->{'schema'} = $schema; } else { delete $self->{'schema'}; } } return Lire::DlfSchema::load_schema( $self->{'schema'} || $self->{'superservice'} ); } =pod =head2 joined_schemas( [ $new_schemas ] ) Returns as an array reference, the list of schemas that are joined in this specification. If $new_schemas is set, the list of joined schemas will be changed to that list. This is an array reference of schema name. All of these schemas should be join compatible with the schema specified in the schema() attribute. =cut sub joined_schemas { my ( $self, $new_schemas ) = @_; if ( defined $new_schemas ) { check_object_param( $new_schemas, 'new_schemas', 'ARRAY' ); my $schema = $self->schema(); foreach my $name ( @$new_schemas ) { croak "no schema '$name'" unless Lire::DlfSchema->has_schema( $name ); my $joined = Lire::DlfSchema::load_schema( $name ); croak "cannot join '$name' schema with '" . $schema->id() . "'" unless $self->schema()->can_join_schema( $joined ); } @{$self->{'_joined_schemas'}} = @$new_schemas; } return $self->{'_joined_schemas'}; } =pod =head2 schemas() Returns in an array reference all the schemas used by this specification. This will include the base schema as well as any joined schemas. =cut sub schemas { my $self = $_[0]; return [ $self->schema()->id(), @{$self->{'_joined_schemas'}} ]; } =pod =head2 has_field( $name ) Returns whether the field named $name is available in this specification's schema or any of its joined schema. =cut sub has_field { my ( $self, $name ) = @_; check_param( $name, 'name' ); return 1 if $self->schema()->has_field( $name ); foreach my $schema_name ( @{$self->{'_joined_schemas'}} ) { my $schema = Lire::DlfSchema::load_schema( $schema_name ); return 1 if $schema->has_field( $name ); } return 0; } =pod =head2 field( $name ) Returns the Lire::Field object named $name present in one of the specification's joined schema. =cut sub field { my ( $self, $name ) = @_; check_param( $name, 'name' ); croak ( "no field '$name' in this specification's schemas: " . join( ", ", $self->schema()->id(), @{$self->{'_joined_schemas'}} )) unless $self->has_field( $name ); return $self->schema()->field( $name ) if $self->schema()->has_field( $name ); foreach my $schema_name ( @{$self->{'_joined_schemas'}} ) { my $schema = Lire::DlfSchema::load_schema( $schema_name ); return $schema->field( $name ) if $schema->has_field( $name ); } die "ASSERT: shouldn't be reached"; } =pod =head2 title( [ $new_title ] This method returns the title of this specification. If $new_title is set, the specification's title will be changed to that value. The returned value is localized if a translation string is available. The domain used for translation is 'lire-<superservice'. =cut sub title { my ( $self, $title ) = @_; if ( defined $title ) { $self->{'title'} = $title; } return dgettext( 'lire-' . $self->superservice(), $self->{'title'} ); } =pod =head2 description( [ $new_description ] This method returns the description of this specification. If $new_description is set, the specification's description will be changed to that value. That description is a DocBook string describing the specification's purpose. The returned value is localized if a translation string is available. The domain used for translation is 'lire-<superservice'. =cut sub description { my ( $self, $desc ) = @_; if ( defined $desc ) { $self->{'description'} = $desc; } return dgettext_para( 'lire-' . $self->superservice(), $self->{'description'} ); } sub has_param { my ( $self, $name ) = @_; return exists $self->{'params'}{$name}; } sub param { my ( $self, $name, $param ) = @_; if ( defined $param ) { croak "param has invalid name $name != " . $param->name() unless $name eq $param->name(); $self->{'params'}{$name} = $param; } croak "Lire::XMLSpecContainer::param: no param $name defined" unless $self->has_param( $name ); my $p = $self->{'params'}{$name}; if ( @_ == 3 && ! defined $param) { # Remove it delete $self->{'params'}{$name}; } return $p; } sub param_names { my ( $self ) = @_; return map { $_->name() } values %{$self->{'params'}}; } sub resolve_param_ref { my ( $self, $value ) = @_; return undef unless (defined $value); if ( substr( $value, 0, 1) eq '$') { my $pname = substr( $value, 1); croak "no such parameter: '$pname'" unless (defined $self->{'params'}{$pname}); return $self->{'params'}{$pname}->value(); } else { return $value; } } =pod =head2 display_title( [ $new_title ] This method returns the title that will be displayed in the generated specification. This value can contains reference to the specification's parameters using the '$name' syntax. If $new_title is set, the specification's display title will be changed to that value. The returned value is localized if a translation string is available. The domain used for translation is 'lire-<superservice'. =cut sub display_title { my ( $self, $title ) = @_; if ( defined $title ) { my @wrong = $self->check_params( $title ); if ( @wrong == 1 ) { croak "non-existent parameter '", $wrong[0], "' used in display title\n"; } elsif ( @wrong > 1 ) { croak "non-existent parameters (", join( ", ", @wrong ), ") are used in display title\n"; } $self->{'display_title'} = $title; } return dgettext( 'lire-' . $self->superservice(), $self->{'display_title'} ); } =pod =head2 display_description( [ $new_description ] This method returns the description that will be displayed in the generated report. This value can contains reference to the specification's parameters using the '$name' syntax. If $new_description is set, the specification's description will be changed to that value. That description is a DocBook string describing the specification's purpose. The returned value is localized if a translation string is available. The domain used for translation is 'lire-<superservice'. =cut sub display_description { my ( $self, $desc ) = @_; if ( @_ == 2 ) { my @wrong = $self->check_params( $desc ); if ( @wrong == 1 ) { croak "non-existent parameter '", $wrong[0], "' used in display description\n"; } elsif ( @wrong > 1 ) { croak "non-existent parameters (", join( ", ", @wrong ), ") are used in display description\n"; } # Modify the description $self->{'display_description'} = $desc; } return dgettext_para( 'lire-' . $self->superservice(), $self->{'display_description'} ); } =pod =head2 expanded_display_title() Returns display_title() with parameters reference expanded. =cut sub expanded_display_title { my $self = $_[0]; return $self->expand_params( $self->display_title() ); } =pod =head2 expanded_display_description() Returns display_description() with parameters reference expanded. =cut sub expanded_display_description { my ( $self ) = @_; return $self->expand_params( $self->display_description() ); } # ------------------------------------------------------------------------ # Method check_params($str) # # Extracts the $ parameters contained in $str and returns the # list of parameter which aren't available. # # Returns the empty list if all parameters are valid sub check_params { my ($self, $str ) = @_; my @wrong = (); my @params = $str =~ m|(?<!\$)\$([a-zA-Z]+[-:.\w]+)|g; foreach my $p ( @params ) { push @wrong, $p unless $self->has_param( $p ); } return @wrong; } sub expand_params { my ($self, $str) = @_; return $str if ( ! defined $str ); # Replace all occurence of $name with the value of the # parameter with the same name. Ignore $$name which will become $name. # Will croak on non-existent parameters. $str =~ s{(?<!\$)\$([a-zA-Z]+[-:.\w]+)}{$self->param($1)->value()}eg; # Unescape $$ $str =~ s{\$\$}{\$}g; return $str; } =pod =head2 print( $fh ) Prints this specification as XML on $fh. =cut sub print { my ($self, $fh) = @_; $fh ||= \*STDOUT; my $root = $self->root_element(); # # The header # print $fh <<EOF; <?xml version="1.0"?> <!DOCTYPE lire:$root PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.1//EN" "http://www.logreport.org/LRSML/2.1/lrsml.dtd"> EOF print $fh qq{<lire:$root xmlns:lire="http://www.logreport.org/LRSML/" xmlns:lrcml="http://www.logreport.org/LRCML/" id="$self->{'id'}" superservice="$self->{'superservice'}"}; print $fh qq{ schema="$self->{'schema'}"} if defined $self->{'schema'}; print $fh $self->root_xml_attrs(); print $fh ">\n\n"; # # Title and description # my $title = xml_encode( $self->{'title'} ); print $fh <<EOF; <lire:title>$title</lire:title> <lire:description>$self->{'description'}</lire:description> EOF # # Parameter specifications # if ( keys %{$self->{'params'}}) { print $fh " <lire:param-spec>\n"; foreach my $p ( values %{$self->{'params'}} ) { my $name = $p->name(); my $type = $p->type(); my $default = xml_encode( $p->default() ); my $desc = $p->description(); print $fh qq{ <lire:param name="$name" type="$type"}; print $fh qq{ default="$default"} if defined $default; if (defined $desc ) { print $fh <<EOF; > <lire:description>$desc</lire:description> </lire:param> EOF } else { print $fh "/>\n\n"; } } print $fh " </lire:param-spec>\n"; } # # Display-spec # my $display_title = xml_encode( $self->{'display_title'} ); print $fh <<EOF; <lire:display-spec> <lire:title>$display_title</lire:title> EOF print $fh " <lire:description>\n", $self->display_description, " </lire:description>\n\n" if $self->display_description; print $fh <<EOF; </lire:display-spec> EOF $self->print_children( $fh, 1 ); print $fh <<EOF; </lire:$root> EOF return; } sub has_spec { my ( $self, $super, $id ) = @_; check_param( $super, 'superservice', \&check_superservice ); check_param( $id, 'id', \&check_xml_name ); foreach my $dir ( @{$self->spec_path()} ) { return 1 if -f "$dir/$super/$id.xml"; } return 0; } sub list_specs { my ( $self, $super ) = @_; check_param( $super, 'superservice', \&check_superservice ); my %result = (); foreach my $dir ( @{$self->spec_path()} ) { next unless -d "$dir/$super" && -r "$dir/$super"; opendir my $dh, "$dir/$super" or die "opendir failed: $!\n"; foreach my $file ( readdir $dh ) { next unless $file =~ /^([a-zA-Z][a-zA-Z0-9._-]+)\.xml$/; $result{$1} = 1; } closedir $dh; } return [ keys %result ]; } sub file_from_id { my ( $self, $super, $id ) = @_; check_param( $super, 'superservice', \&check_superservice ); check_param( $id, 'id', \&check_xml_name ); foreach my $dir ( @{$self->spec_path()} ) { return "$dir/$super/$id.xml" if -f "$dir/$super/$id.xml"; } croak( "can't find '$super' ", ref $self || $self, " XML specification '$id' in \"", join( ":", @{$self->spec_path()} ), '"' ); } sub new_from_config { my ( $self, $value ) = @_; my $def = $value->Lire::Config::Dictionary::as_value(); my ( $super, $type ) = $value->name() =~ qr/$Lire::Config::XMLSpecListSpec::NAME_RE/; my $spec = $self->load( $super, $type ); $spec->display_title( $def->{'title'} ) if $def->{'title'}; foreach my $name ( $spec->param_names() ) { $spec->param( $name )->value( $def->{$name} ); } return $spec; } ######################################################################## # METHODS TO OVERRIDE ######################################################################## sub print_children { my ( $self, $fh, $indent ) = @_; croak "unimplemented method: ", ref $self || $self, "::print_children\n"; } sub spec_path { croak "unimplemented method: ", ref $_[0] || $_[0], "::spec_path\n"; } sub root_element { my ( $self ) = @_; croak "unimplemented method: ", ref $self || $self, "::root_element\n"; } sub root_xml_attrs { return ""; } 1; __END__ =pod =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::FilterSpec(3pm), Lire::XMLSpecParser(3pm) =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <wolfgang@logreport.org> =head1 VERSION $Id: XMLSpecContainer.pm,v 1.41 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������lire-2.1.1/all/lib/Lire/PluginManager.pm������������������������������������������������������������0000644�0001750�0001750�00000023524�10460673255�014705� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::PluginManager; use strict; use vars qw/ $instance %plugin_types /; use Carp; use Lire::Config; use Lire::Error qw/ file_not_readable /; use Lire::OldDlfAdapter; use Lire::Utils qw/ file_content check_param check_object_param /; $instance = new Lire::PluginManager(); %plugin_types = ( 'output_format' => 'Lire::OutputFormat', 'chart_type' => 'Lire::ChartType', 'dlf_analyser' => 'Lire::DlfAnalyser', 'dlf_converter' => 'Lire::DlfConverter', ); sub new { return bless { 'output_format' => {}, 'dlf_analyser' => {}, 'dlf_converter' => {}, 'chart_type' => {}, }, shift; } =pod =head1 NAME Lire::PluginManager - Manages the Lire plugins. =head1 SYNOPSIS use Lire::PluginManager; Lire::PluginManager->register_default_plugins(); my $plugin = new MyDlfConverter(); Lire::PluginManager->register_plugin( $plufin ); my $plugins = Lire::PluginManager->plugins( 'dlf_analyser' ); my $converter = Lire::PluginManager->get_plugin('dlf_analyser', 'combined'); =head1 DESCRIPTION All method can be called as class method on the Lire::PlugingManager module or on an instance. =head2 PLUGIN TYPES There are four kind of plugins defined in Lire: dlf_analyser, dlf_converter, chart_type and output_format. =head2 instance() Returns the singleton instance of the PluginManager =cut sub instance { return $instance; } sub check_type { my ( $type ) = @_; check_param( $type, 'type' ); return 1 if exists $plugin_types{$type}; my @types = map { "'$_'" } sort keys %plugin_types; croak "'type' parameter should be one of " . join ( ", ", @types[0..$#types-1] ) . " or $types[-1]: '$type'"; } =pod =head2 plugin_names( $type ) Returns an array reference containing the names of all registered plugin of type $type. =cut sub plugin_names { my ( $self, $type ) = @_; $self = $instance unless ref $self; check_type( $type ); return [ keys %{$self->{$type}} ]; } =pod =head2 plugins( $type ) Returns an array reference containing all the Plugin objects registerd for $type. =cut sub plugins { my ( $self, $type ) = @_; $self = $instance unless ref $self; check_type( $type ); return [ values %{$self->{$type}} ]; } =pod =head2 has_plugin( $type, $name ) Returns true if there is a Lire::Plugin named $name registered for type $type. =cut sub has_plugin { my ( $self, $type, $name ) = @_; $self = $instance unless ref $self; check_param( $name, 'name' ); check_type( $type ); return exists $self->{$type}{$name}; } =pod =head2 get_plugin( $type, $name ) Returns the Lire::Plugin object named $name of type $type. Croaks when there is no plugin registerd under that name. =cut sub get_plugin { my ( $self, $type, $name ) = @_; $self = $instance unless ref $self; check_param( $name, 'name' ); check_type( $type ); croak "no '$type' plugin '$name' registered" unless $self->has_plugin( $type, $name ); return $self->{$type}{$name}; } =pod =head2 register_plugin( $plugin ) Registers the Lire::Plugin $plugin. The type and name of the plugin are queried using the Lire::Plugin interface. An error will be thrown if there is already a plugin registered under the same name and type. =cut sub register_plugin { my ( $self, $plugin ) = @_; $self = $instance unless ref $self; check_object_param( $plugin, 'plugin', 'Lire::Plugin', ); my $type = $plugin->type(); croak( "plugin '", $plugin->name(), "' has an unknown type: '$type'" ) unless exists $plugin_types{$type}; croak( "'$type' plugin should be a '$plugin_types{$type}' instance: '", ref($plugin), "'" ) unless UNIVERSAL::isa( $plugin, $plugin_types{$type} ); croak( "there is already a '$type' plugin registered under name '", $plugin->name(), "'" ) if $self->has_plugin( $type, $plugin->name() ); $self->{$type}{$plugin->name()} = $plugin; return; } =pod =head2 unregister_plugin( $type, $name ) Unregister the plugin $name of type $type. The method will dies if there is no such plugin. =cut sub unregister_plugin { my ( $self, $type, $name) = @_; $self = $instance unless ref $self; check_param( $name, 'name' ); check_type( $type ); croak "no '$type' plugin '$name' registered" unless $self->has_plugin( $type, $name ); delete $self->{$type}{$name}; return; } =pod =head2 analysers_by_src( $schema ) Returns in an array reference all the analysers that declare $schema as their src_schema(). =cut sub analysers_by_src { my ( $self, $schema ) = @_; check_param( $schema, 'schema' ); my @result = (); foreach my $analyser ( @{$self->plugins( 'dlf_analyser' )} ) { push @result, $analyser if $analyser->src_schema() eq $schema; } return \@result; } =pod =head2 analysers_by_dst( $schema ) Returns in an array reference all the analysers that declare $schema as their dst_schema(). =cut sub analysers_by_dst { my ( $self, $schema ) = @_; check_param( $schema, 'schema' ); my @result = (); foreach my $analyser ( @{$self->plugins( 'dlf_analyser' )} ) { push @result, $analyser if $analyser->dst_schema() eq $schema; } return \@result; } =pod =head2 register_default_plugins() This method will load and initialize all the plugins available. The plugins are registered by executing all the perl scripts found in the directories listed in the 'plugins_init_path' configuration variable. These scripts should call Lire::PluginManager->register_plugin() to register the plugins. For compatibility with previous versions of Lire, it will also registers the DlfConverters initialized using older mechanism. =cut sub register_default_plugins { my $self = $_[0]; $self = $instance unless ref $self; my $init_files = $self->_init_files( Lire::Config->get( 'plugins_init_path' ) ); foreach my $init_file ( @$init_files ) { eval file_content( $init_file ); warn( "error in initialiser '$init_file': $@\n" ) if $@; } $self->_create_old_dlf_adapters(); $self->_load_dlf_adapters(); return; } sub _create_old_dlf_adapters { my $self = $_[0]; my $convertors_dir = Lire::Config->get( 'lr_old_convertors_dir' ); my $address_file = Lire::Config->get( 'lr_old_address_file' ); my $service2schema = $self->_parse_old_map_file( $address_file ); while ( my ($service, $schema) = each %$service2schema ) { unless ( Lire::DlfSchema->has_superservice( $schema )) { warn "invalid superservice '$schema' assigned to service '$service'\n"; next; } my $script = $convertors_dir .'/' . $service . '2dlf'; if ( -x $script ) { my $adapter = new Lire::OldDlfAdapter( $schema, $script ); $self->register_plugin( $adapter ); } else { warn "can't find executable $service" . "2dlf in $convertors_dir\n"; } } } sub _parse_old_map_file { my ($self, $file) = @_; my %map = (); open my $fh, $file or croak( file_not_readable( $file ) ); my $line; while ( defined($line = <$fh>) ) { next if $line =~ /^#/; # Skip comments next if $line =~ /^\s*$/; # Skip empty lines my ($key, $value) = $line =~ /^(\S+)\s+(\S+)\s*(#.*)?$/ or warn "can't parse line $. of file '$file'\n"; $map{$key} = $value if defined $key; } close $fh; return \%map; } sub _load_dlf_adapters { my $self = $_[0]; my $init_files = $self->_init_files( Lire::Config->get( 'lr_converters_init_path' ) ); foreach my $init_file ( @$init_files ) { my $initializer = eval { file_content( $init_file ) }; if ( $@ ) { warn "error reading DLF converter initializer file '$init_file': $@\n"; next; } my @converters = eval $initializer; if ( $@ ) { warn "error while running initializer in '$init_file': $@\n"; next; } foreach my $c ( @converters ) { if ( UNIVERSAL::isa( $c, 'Lire::DlfConverter' ) ) { $self->register_plugin( $c ); } else { warn "initializaer '$init_file' didn't return a Lire::DlfConverter object: $c\n"; } } } } sub _init_files { my ( $self, $dirs ) = @_; my @initializers = (); my %dirs; foreach my $dir ( @$dirs ) { next if exists $dirs{$dir}; $dirs{$dir} = 'done'; opendir my $dh, $dir or croak "opendir failed '$dir': $!"; foreach my $file ( map { "$dir/$_" } readdir $dh ) { next unless -f $file; push @initializers, $file; } closedir $dh; } return \@initializers; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::Plugin(3pm), Lire::OutputFormat(3pm), Lire::DlfAnalyser(3pm), Lire::DlfConverter(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: PluginManager.pm,v 1.8 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputJob.pm����������������������������������������������������������������0000644�0001750�0001750�00000017513�10460673255�014110� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::OutputJob; use strict; use Lire::OutputFormat; use Lire::Utils qw/check_param check_object_param/; use Lire::PluginManager; use Carp; =pod =head1 NAME Lire::OutputJob - Object used to represent a configured formatting of a report =head1 SYNOPSIS use Lire::OutputJob; use Lire::OutputFormat; my $email = new Lire::OutputJob( 'email', $output, $output_cfg, 'emails' => [ 'email@domain.org' ] ); $email->run( 'report.xml' ); my $file = new Lire::OutputJob( 'file', $output, $output_cfg, 'filename' => '/var/www/reports/daily-%Y%m%d' ); $file->run( 'report.xml' ); =head1 DESCRIPTION The Lire::OutputJob objects are used to represent how a report should formatted. These objects are most often created from the Lire configuration. (The 'output_jobs' specification.) =head1 new( $destination_type, $format, $format_cfg, ... ); Create a new Lire::OutputJob object. Two parameters are required: =over =item $destination_type Can be either 'email' or 'file'. =item $format A Lire::OutputFormat object. =item $format The configuration data that will be passed to the OutputFormat object. =back The method will returns an instance of Lire::EmailOutputJob or Lire::FileOutputJob. =cut sub new { my ( $pkg, $type, $format, $format_cfg, %args ) = @_; check_param( $type, 'type', qr/^(email|file)$/, "'type' parameter should be one of 'email' or 'file'" ); check_object_param( $format, 'format', 'Lire::OutputFormat' ); check_param( $format_cfg, 'format_cfg' ); my $self = { '_format' => $format, '_format_cfg' => $format_cfg, }; if ( $type eq 'email' ) { bless $self, 'Lire::EmailOutputJob'; } else { bless $self, 'Lire::FileOutputJob'; } $self->init( %args ); return $self; } =pod =head2 format Returns the Lire::OutputFormat associated with this OutputJob. =cut sub format { return $_[0]{'_format'}; } =pod =head2 format_cfg Returns the configuration data that will be used when formatting the report. =cut sub format_cfg { return $_[0]{'_format_cfg'}; } =pod =head2 run( $report_file ) Formats and sends or save the XML report $report_file according the OutputJob parameters. =cut sub run { croak ref shift, "::run unimplemented"; } sub new_from_config { my ( $pkg, $value ) = @_; my $format = Lire::PluginManager->get_plugin( 'output_format', $value->get( 'format' )->get_plugin() ); return new Lire::OutputJob( $value->get( 'destination' )->get_plugin(), $format, $value->get( 'format' )->get_properties()->as_value(), %{$value->get( 'destination' )->get_properties()->as_value()} ); } package Lire::EmailOutputJob; use base qw/Lire::OutputJob/; use Lire::Utils qw/check_object_param file_content/; eval "use MIME::Entity"; sub init { my ( $self, %args ) = @_; check_object_param( $args{'emails'}, 'emails', 'ARRAY' ); $self->{'_emails'} = $args{'emails'}; $self->{'_subject'} = $args{'subject'} ? $args{'subject'} : ''; $self->{'_subject'} = $args{'subject'} ? $args{'subject'} : ''; $self->{'_extra_file'} = $args{'extra_file'}; return; } =pod =head1 Lire::EmailOutputJob =head2 Extra parameters for 'email' type =over =item emails An array reference to the emails that will receive the formatted report. =item subjet The subject of the email. =item extra_file An additional text file that will be appended to text report or attach to other report types. =item =back =head2 emails() Returns as an array the emails to which the report will be sent. =cut sub emails { return @{$_[0]{'_emails'}}; } =pod =head2 subject() Returns the subject of the email. =cut sub subject { return $_[0]{'_subject'}; } =pod =head2 extra_file() Returns the filename that will be appended to the text report or attach to the message for other report's type. =cut sub extra_file { return $_[0]{'_extra_file'}; } sub run { my ( $self, $report_file ) = @_; my $msg = $self->format()->mime_report( $report_file, $self->format_cfg() ); if ( $self->{'_extra_file'} ) { if ( $msg->mime_type() eq 'text/plain' ) { my $new_content = $msg->bodyhandle()->as_string() . "\n" . file_content( $self->{'_extra_file'} ); my $io = $msg->open( 'w' ); $io->print( $new_content ); $io->close(); } else { my $entity = MIME::Entity->build( 'Type' => 'multipart/mixed' ); $entity->add_part( $msg ); $msg = $entity; $msg->attach( 'Type' => 'text/plain', 'Path' => $self->{'_extra_file'} ); } } $msg->head()->set( 'To', join( ", ", @{$self->{'_emails'}} ) ); my $from = Lire::Config->get( 'lr_mail_from' ) || $ENV{'EMAIL'}; $msg->head()->set( 'From', $from ) if $from; $msg->head()->set( 'Subject', $self->subject() ); my $reply_to = Lire::Config->get( 'lr_mail_reply_to' ); $msg->head()->set( 'Reply-To', $reply_to ) if $reply_to; my $pid = open( my $fh, "|-" ); die "can't fork: $!\n" unless defined $pid; if ( $pid ) { # Parent $msg->print( $fh ); close $fh or die "error: sendmail exited with non zero status: $?\n"; } else { # Children, execute sendmail # We use this form of exec so that @to can't be used to trick # a shell. exec( Lire::Config->get( 'sendmail_path' ), @{$self->{'_emails'}} ) or do { print STDERR "error executing sendmail: $!\n"; # Since we are a fork, we don't want our die trapped. CORE::exit(1); }; } return; } package Lire::FileOutputJob; use base qw/Lire::OutputJob/; use Lire::Utils qw/check_param/; use POSIX qw/strftime/; sub init { my ( $self, %args ) = @_; check_param( $args{'file'}, 'file' ); $self->{'_file'} = $args{'file'}; return; } =pod =head1 Lire::FileOutputJob =head2 Extra parameters for 'file' type. =over 4 =item file A file path with possible strftime(3pm) interpolation. This will be were the formatted report will be saved. =back =head2 file() Returns this OutputJob destination file. =cut sub file { return $_[0]{'_file'}; } =pod =head2 output_file( [$time] ) Returns the destination file with strftime(3) specifier interpolated. =cut sub output_file { my ( $self, $time ) = @_; $time ||= time(); return strftime( $self->{'_file'}, localtime $time ); } sub run { my ( $self, $report, $time ) = @_; check_param( $report, 'report' ); $time ||= time(); $self->format()->format_report( $report, $self->output_file( $time ), $self->format_cfg() ); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::ReportJob(3pm) Lire::OutputFormat(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: OutputJob.pm,v 1.8 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/W3CExtendedLog.pm�����������������������������������������������������������0000644�0001750�0001750�00000032431�10460673256�014671� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::W3CExtendedLog; use strict; use base qw/ Exporter /; use vars qw/ @EXPORT_OK %DEFAULTS_TYPE2REGEX %DEFAULTS_IDENTIFIER2TYPE /; use Exporter; use Time::Local; use Lire::Logger; BEGIN { @EXPORT_OK = qw/ w3c_time uri_decode string_decode /; # Maps W3C types to regex %DEFAULTS_TYPE2REGEX = ( 'integer' => '(\d+|-)', 'fixed' => '(\d+(?:\.\d+)?|-)', 'uri' => '(\S+)', 'date' => '(\d\d\d\d-\d\d-\d\d)', 'time' => '(\d\d:\d\d(?::\d\d(?:\.\d+)?)?)', # Match anything beween a starting " and another followed by a space # (Embedded " are doubled) -> "String with a "" in it" 'string' => '"((?:[^"]|"")*)"', 'name' => '([-_.0-9a-zA-Z]+)', # This also match invalid domain names 'address' => '(\d+\.\d+\.\d+\.\d+|-)', ); # Maps identifier to type %DEFAULTS_IDENTIFIER2TYPE = ( 'count' => 'integer', 'time-from' => 'fixed', 'time-to' => 'fixed', 'interval' => 'integer', 'ip' => 'address', 'dns' => 'name', 'status' => 'integer', 'comment' => 'string', 'uri' => 'uri', 'uri-stem' => 'uri', 'uri-query' => 'uri', 'method' => 'name', 'username' => 'uri', 'date' => 'date', 'time' => 'time', 'port' => 'integer', 'time-taken' => 'fixed', 'bytes' => 'integer', 'cached' => 'integer', ); } my $debug = 0; sub debug { $debug and lr_debug($_[0]); } ######################################################################## # UTILITY FUNCTIONS ######################################################################## sub uri_decode { $_[0] =~ s/\%(..)/hex( '0x' . $1)/ge; $_[0] =~ tr/+/ /; } sub string_decode { # Transform "" into " $_[0] =~ tr/"/"/s; } sub w3c_time { my ( $date, $time ) = @_; my ($year, $month, $mday ) = $date =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/ or die "invalid date string: $date\n"; my ($hours, $min, $sec, $msec ) = $time =~ /^(\d\d):(\d\d)(?::(\d\d)(?:\.(\d+))?)?$/ or die "invalid time string: $time\n"; $month--; $year -= 1900; # Yes, W3C Extended Log time are in UTC time. return timegm( $sec || 0, $min, $hours, $mday, $month, $year ); } ######################################################################## # PARSER METHODS ######################################################################## sub new { my $self = shift; my $class = ref($self) || $self; bless $self = { # Copy in attributes so that they can be overidden 'type2regex' => { %DEFAULTS_TYPE2REGEX }, 'identifier2type' => { %DEFAULTS_IDENTIFIER2TYPE }, 'log_date' => undef, 'log_time' => undef, 'version' => undef, 'sofware' => undef, 'fields' => undef, 'is_iis' => undef, 'in_header' => 1, 'skip_to_next_header' => 0, }, $class; return $self; } sub field2re { my ( $self, $field ) = @_; if ( $field =~ /^\w+\(.*\)$/ ) { # Header if ( $self->{'is_iis'} ) { return $self->{'type2regex'}{'uri'}; } else { return $self->{'type2regex'}{'string'}; } } else { # csrx are prefixes used in field identifiers, cf W3C specs my ( $identifier ) = $field =~ /^(?:[csrx]{1,2}-)?(.*)$/; my $type = $self->{'identifier2type'}{$identifier}; unless ( defined $type ) { lr_warn( "identifier '$identifier' (constructed from '$field') " . "not found in identifier2type property. Will use uri type" ); $debug and do { debug( "dumping identifier2type hash" ); while ((my $k, my $v) = each %{ $self->{'identifier2type'} }) { if (defined $v) { debug( "identifier2type{'$k'} = '$v'" ); } else { debug( "identifier2type{'$k'} undefined" ); } } }; return $self->{'type2regex'}{'uri'}; } else { if ( $type eq 'string' && $self->{'is_iis'} ) { return $self->{'type2regex'}{'uri'}; } elsif (defined $self->{'type2regex'}{$type}) { return $self->{'type2regex'}{$type}; } else { lr_warn( "unknown type: $type. Will return uri type" ); return $self->{'type2regex'}{'uri'}; } } } } sub field2decoder { my ( $self, $field ) = @_; if ( $field =~ /^\w+\(.*\)$/ ) { # Header if ( $self->{'is_iis'} ) { return \&uri_decode; } else { return \&string_decode; } } else { my ( $identifier ) = $field =~ /^(?:[csrx]{1,2}-)?(.*)$/; my $type = $self->{'identifier2type'}{$identifier}; return undef unless defined $type; if ( $type eq 'string' && $self->{'is_iis'} ) { return \&uri_decode; } elsif ( $type eq 'string' ) { return \&string_decode; } return undef; } } sub build_parser { my ( $self ) = @_; my @fields = split /\s+/, $self->{'fields'}; # Quick check die( "we don't support aggregated records: $self->{'fields'}\n" ) if $fields[0] eq 'count'; my @re = (); my %decoders = (); foreach my $f ( @fields ) { if (defined $self->field2re( $f )) { push @re, $self->field2re( $f ); } else { die( "internal inconsistency: field2re undefined in '$f'. " . "aborting.\n") } my $decoder = $self->field2decoder( $f ); $decoders{$f} = $decoder if $decoder; } my $sep = $self->{'tab_sep'} ? '\t' : '\s+'; my $re = "^" . join ( $sep, @re) . "\$"; lr_info( "will use $re as lexer" ); lr_info( "to parse fields: ", join ", ", @fields ); my $rx = qr/$re/; $self->{'w3c_parser'} = sub { # Remove potential extra CR of DOS line ending $_[0] =~ s/\r?\n?$//; my @rec = $_[0] =~ /$rx/ or die "lexer failed\n"; my $i = 0; my %w3c = map { $fields[$i++] => $_ } @rec; # Decode fields foreach my $name ( keys %decoders ) { $decoders{$name}->( $w3c{$name} ); } # Decode timestamp my $date = $w3c{'date'} || $self->{'log_date'}; if ( defined $date && exists $w3c{'time'} ) { $w3c{'lire_time'} = w3c_time( $date, $w3c{'time'} ); } return \%w3c; } } sub parse_directive { my ( $self, $line ) = @_; $line =~ s/\r?\n?$//; # To remove potential extra CR of DOS line ending die "not a directive line: $line\n" unless $line =~ /^#/; my ( $directive, $text ) = $line =~ /^#(\w+): (.*)/ or die( "error parsing directive: $line\n" ); SWITCH: for ( $directive ) { /^Version$/i && do { $self->{'version'} = $text + 0; die( "Unsupported format version: $text != 1.0\n" ) unless $self->{'version'} == 1; lr_info( "W3C Extended Log Format ", $text ); last SWITCH; }; /^Fields$/i && do { if ( $self->{'fields'} ) { if ( $self->{'fields'} ne $text ) { $self->{'skip_to_next_header'} = 1; lr_warn( "we don't support switching Fields directive: $text.Ignoring those log records\n"); } last SWITCH; } $self->{'fields'} = $text; # this is reported to occur in MS ISA logs (the one IIS logfiles # we've seen use space as separator in both Fields and the log # itself. Unfortunately, this logfile does _not_ escape spaces # in its values :( ) $self->{'tab_sep'} = $text =~ /\t/; lr_info( "found tabcharacter in Fields declaration; therefore " . "using tab as field separator and allowing non-escaped " . "spaces" ) if $self->{'tab_sep'}; $self->build_parser(); last SWITCH; }; /^Software$/i && do { lr_info( "Log generated by $text" ); $self->{'is_iis'} = $text =~ /Microsoft Internet/; lr_info( "activating IIS specific support" ) if $self->{'is_iis'}; last SWITCH; }; /^Date$/ && do { my $date_re = $self->{'type2regex'}{'date'}; my $time_re = $self->{'type2regex'}{'time'}; ($self->{'log_date'}, $self->{'log_time'} ) = $text =~ /$date_re $time_re/o; if ( defined $self->{'log_date'} && defined $self->{'log_time'} ) { lr_info( "Date: ", $text ); } else { lr_warn( "Invalid date directive: $text" ); } last SWITCH; }; /^(Start-Date|End-Date|Date|Remark)$/ && do { # Ignore those directive lr_info( $directive, ": ", $text ); last SWITCH; }; /^SubComponent$/ && do { lr_info( "ignoring log of SubComponent $text" ); $self->{'skip_to_next_header'} = 1; last SWITCH; }; # Defaults lr_warn( "unknown directive: $line" ); } } sub parse { my ($self, $line) = @_; if ( $line =~ /^#/ ) { if ( $self->{'skip_to_next_header'} && ! $self->{'in_header'} ) { $self->{'skip_to_next_header'} = 0; } $self->{'in_header'} = 1; $self->parse_directive( $line ); } elsif ( $self->{'version'} && $self->{'fields'} ) { $self->{'in_header'} = 0; return undef if $self->{'skip_to_next_header'}; $self->parse_record( $line ); } else { lr_err( "invalid W3C extended log file: must start by Version and Fields directives" ); } } sub parse_record { $_[0]->{'w3c_parser'}->( $_[1] ); } 1; __END__ =pod =head1 NAME Lire::W3CExtendedLog - Base implementation of a W3C Extended Log parser =head1 SYNOPSIS use Lire::W3CExtendedLog; my $parser = new Lire::W3CExtendedLog; my $w3c_rec = $parser->parse( $line ); =head1 DESCRIPTION This module defines objects able to parse W3C Extended Log Format. This log format is defined at http://www.w3.org/TR/WD-logfile.html All attributes of the created object can be overriden by e.g. modules extending the object. The attributes are: =head2 type2regex I<type2regex> is a hash containing key-value pairs like 'name' => '([-_.0-9a-zA-Z]+)' Keys are all data formats for log file field entries as defined in the W3C specification: 'integer', 'fixed', 'uri', 'date', 'time' and 'string', along with 'name' and 'address' types. =head2 identifier2type I<identifier2type> is a hash containing key-value pairs like 'dns' => 'name', 'uri-query' => 'uri', 'ip' => Keys are the W3C defined Field identifiers, with their prefixes stripped off. =head2 field2re I<field2re> is subroutine; when called as $self->{field2re('c-ip')} it will return e.g. '(\d+\.\d+\.\d+\.\d+|-)' Arguments are as found in the Fields directive, so, in an ideal world, should be identifiers. It uses I<type2regex>. =head2 field2decoder I<field2decoder> is a subroutine; it returns one of I<\&uri_decode> , I<\&string_decode> or I<undef>, depending on, a.o., I<is_iis>. It is used by I<build_parser>. =head2 parse I<parse> is the preferred interface to this module. It expects a line as its argument, and returns a reference to a hash (like I<&w3c_parser>), or executes I<&parse_directive>. =head2 parse_directive I<parse_directive> expects a directive in its argument, it fills the object. =head2 w3c_parser I<w3c_parser> is a subroutine; it expects a logline as argument, and returns a reference to a hash, mapping $self->{'fields'} entries to their decoded values. It uses the I<&field2re> and I<&field2decoder> routines. It is build in build_parser. =head2 build_parser I<build_parser> is a subroutine, it builds and returns I<&w3c_parser>. It is called in I<&parse_directive>. =head2 log_date and log_time I<log_date> and I<log_time> contain strings constructed from the Date directive. =head2 version and sofware I<version> and I<software> contain strings constructed from the Version and Software directives, respectively. =head2 fields I<fields> contains the entire string from the Fields directive. =head2 is_iis I<is_iis> is set in case the Software directive contains 'Microsoft Internet' as a substring. It is used to enable IIS specific support. =head2 tab_sep I<tab_sep> is set in case tabs are found in the Fields directive. We assume these will be used in the log itself too, and allow unescaped spaces in the log. Summarizing: &parse --calls--> &parse_directive `--calls--> &w3c_parser &parse_directive --calls--> &build_parser &build_parser --calls--> &field2decoder `--calls--> &field2re `--returns--> &w3c_parser &field2decoder --returns--> &uri_decode, &string_decode &field2re --uses--> %type2regex `--uses--> %identifier2type =head1 BUILDING INHERITING MODULES FIXME . Needs to be written. Steal from w3c_extended2dlf's Lire::WWW::ExtendedLog, which ISA Lire::W3CExtendedLog. =head1 SEE ALSO w3c_extended2dlf(1), ms_isa2dlf(1) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: W3CExtendedLog.pm,v 1.18 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/XMLSpecI18N.pm��������������������������������������������������������������0000644�0001750�0001750�00000016550�10460673256�014031� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::XMLSpecI18N; use strict; use Carp; use File::Basename qw/ basename /; use POSIX qw/ setlocale LC_MESSAGES /; use Lire::Utils qw/ tree_apply check_object_param /; =pod =head1 NAME Lire::XMLSpecI18N - Extract strings for localization from XML Specs =head1 SYNOPSIS use Lire::XMLSpecI18N; =head1 DESCRIPTION FILL ME IN =cut sub new { my ( $class, @specs ) = @_; croak "missing one or more 'specs' parameter" unless @specs; my $self = bless {}, $class; $self->{'_specs'} = []; foreach my $spec (@specs) { check_object_param( $spec, 'spec', [ 'Lire::ReportConfig', 'Lire::DlfSchema', 'Lire::XMLSpecContainer', 'Lire::Config::ConfigSpec' ] ); push @{$self->{'_specs'}}, $spec; } return $self; } sub _generate_ref { my $self = $_[0]; croak( "'_cur_spec' attribute is undef" ) unless defined $self->{'_cur_spec'}; my $spec = $self->{'_cur_spec'}; my $ref; if ( UNIVERSAL::isa( $spec, 'Lire::ReportConfig' ) ) { $ref = basename( $spec->filename() ); } elsif ( UNIVERSAL::isa( $spec, 'Lire::Config::ConfigSpec' ) ) { croak "no 'xml_file' attribute, was Lire;:Config::ConfigSpec->xml_file() called?" unless $spec->xml_file(); $ref = basename( $spec->xml_file() ); } elsif ( UNIVERSAL::isa( $spec, 'Lire::ReportSpec' ) ) { $ref = "report:" . $spec->superservice() . ":" . $spec->id(); } elsif ( UNIVERSAL::isa( $spec, 'Lire::FilterSpec' ) ) { $ref = "filter:" . $spec->superservice() . ":" . $spec->id(); } elsif ( UNIVERSAL::isa( $spec, 'Lire::DlfSchema' ) ) { $ref = "schema:" . $spec->id(); } else { croak "unknown spec reference: $spec"; } print "# REFERENCE: $ref\n"; return; } sub _generate_msgid { my ( $self, $msgid ) = @_; $self->_generate_ref(); $msgid =~ s/(^ +| +$)//gm; $msgid =~ s/\n/ /g; print "__( q{$msgid} );\n"; return; } sub generate_catalog { my $self = $_[0]; # Make sure we get the C strings my $old_locale = setlocale( LC_MESSAGES ); setlocale( LC_MESSAGES, 'C' ); eval { foreach my $spec ( @{ $self->{'_specs'} } ) { $self->{'_cur_spec'} = $spec; if ( $spec->isa( 'Lire::ReportSpec' ) ) { $self->_report_spec_i18n(); } elsif ( $spec->isa( 'Lire::ReportConfig' ) ) { $self->_report_config_i18n(); } elsif ( $spec->isa( 'Lire::Config::ConfigSpec' ) ) { $self->_config_spec_i18n(); } elsif ( $spec->isa( 'Lire::DlfSchema' ) ) { $self->_schema_i18n(); } elsif ( $spec->isa( 'Lire::XMLSpecContainer' ) ) { $self->_xml_spec_i18n(); } else { croak "unknown spec type: $spec"; } } }; setlocale( LC_MESSAGES, $old_locale ); die $@ if $@; return; } sub _report_config_i18n { my $self = $_[0]; check_object_param( $self->{'_cur_spec'}, '_cur_spec', 'Lire::ReportConfig' ); foreach my $sect ( $self->{'_cur_spec'}->sections() ) { $self->_generate_msgid( $sect->title() ); } return; } sub _schema_i18n { my $self = $_[0]; my $spec = $self->{'_cur_spec'}; check_object_param( $self->{'_cur_spec'}, '_cur_spec', 'Lire::DlfSchema' ); $self->_generate_msgid( $spec->title() ); my $desc = $spec->description(); $self->_generate_msgid( $self->_strip_para( $desc ) ) if $desc; foreach my $field ( $spec->isa( 'Lire::ExtendedSchema' ) ? @{$spec->extended_fields()} : @{$spec->fields()} ) { next if $field->name() eq 'dlf_id'; next if $field->name() eq 'dlf_source'; $self->_generate_msgid( $field->label() ); $desc = $field->description(); $self->_generate_msgid( $self->_strip_para( $desc ) ) if $desc; } return; } sub _xml_spec_i18n { my $self = $_[0]; my $spec = $self->{'_cur_spec'}; check_object_param( $self->{'_cur_spec'}, '_cur_spec', 'Lire::XMLSpecContainer' ); $self->_generate_msgid( $spec->title() ); my $desc = $spec->description(); $self->_generate_msgid( $self->_strip_para( $desc ) ) if $desc; foreach my $name ( $spec->param_names() ) { my $param = $spec->param( $name ); $desc = $param->description(); $self->_generate_msgid( $self->_strip_para( $desc ) ) if $desc; } $self->_generate_msgid( $spec->display_title() ); $desc = $spec->display_description(); $self->_generate_msgid( $self->_strip_para( $desc ) ) if $desc; return; } sub _report_spec_i18n { my $self = $_[0]; check_object_param( $self->{'_cur_spec'}, '_cur_spec', 'Lire::ReportSpec' ); my $spec = $self->{'_cur_spec'}; $self->_xml_spec_i18n(); tree_apply( $spec->calc_spec(), sub { my $op = $_[0]; return $op->isa( 'Lire::Aggregator' ) ? $op->ops() : []; }, sub { my $op = $_[0]; $self->_generate_msgid( $op->label() ) if $op->has_label(); } ); return; } sub _config_spec_i18n { my $self = $_[0]; check_object_param( $self->{'_cur_spec'}, '_cur_spec', 'Lire::Config::ConfigSpec' ); my $spec = $self->{'_cur_spec'}; tree_apply( $spec, sub { my $comp = $_[0]; return [] unless $comp->isa( 'Lire::Config::CompoundSpec' ); return [ sort( { $a->name() cmp $b->name() } $comp->components() ) ]; }, sub { my $comp = $_[0]; $self->_generate_msgid( $comp->summary() ) if $comp->summary() ne $comp->name(); my $desc = $comp->description(); $self->_generate_msgid( $self->_strip_para( $desc ) ) if $desc; } ); return; } sub _strip_para { my ( $self, $string ) = @_; $string =~ s{(^\s*<para>|</para>\s*$)}{}g; return $string; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO lr_spec2pot(1) =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <wolfgang@logreport.org> =head1 VERSION $Id: XMLSpecI18N.pm,v 1.11 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/XMLParser.pm����������������������������������������������������������������0000644�0001750�0001750�00000050112�10460673256�013763� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::XMLParser; use strict; use Lire::Error qw/file_not_readable/; use Lire::Utils qw/check_param/; use XML::Parser; =pod =head1 NAME Lire::XMLParser - Base object-oriented XML parser. =head1 SYNOPSIS package MyParser; use base qw/ Lire::XMLParser /; =head1 DESCRIPTION This module makes it possible to write object-oriented parser using the non-oo XML::Parser module. =cut sub new { return bless { '_xml_collectors' => {}, '_xml_stacks' => {}, }, shift; } sub Init { my $expat = $_[0]; my $self = $expat->{'_LireXMLParser'}; $self->{'_xml_expat'} = $expat; $self->_build_ns_maps(); $self->_build_dtd(); $self->parse_start(); return; } sub Start { my ( $expat, $name, %attr ) = @_; my $self = $expat->{'_LireXMLParser'}; my $element = $self->_prefixed_name( $name ); $self->error( "encountered unknown element '$element'" ) unless exists $self->{'_xml_elements'}{$element}; my $parent = $self->current_element(); $self->error( "'$element' element cannot appear in the context of '$parent'" ) unless ( ! defined $parent || exists $self->{'_xml_elements'}{$parent}{'content'}{$element} ); $self->element_start( $element, \%attr ); return; } sub Char { my ( $expat, $text ) = @_; my $self = $expat->{'_LireXMLParser'}; my $element = $self->current_element(); if ( $self->{'_xml_elements'}{$element}{'content'}{'PCDATA'} ) { $self->pcdata( $text ); } elsif ( $text =~ /^\s*$/ ) { $self->ignorable_ws( $text ); } else { $self->error( "non-white space character in element '$element' which cannot contain PCDATA" ); } return; } sub End { my ( $expat, $name ) = @_; my $self = $expat->{'_LireXMLParser'}; my $element = $self->_prefixed_name( $name ); $self->element_end( $element ); return; } sub Final { my $expat = $_[0]; my $self = $expat->{'_LireXMLParser'}; delete $self->{'_xml_expat'}; return $self->parse_end(); } sub _build_ns_maps { my $self = $_[0]; my $map = $self->namespaces(); $self->{'_xml_prefix2ns'} = {}; $self->{'_xml_ns2prefix'} = {}; while ( my ( $ns, $prefix ) = each %{$map} ) { die "missing prefix for namespace '$ns'\n" unless defined $prefix && length $prefix; die "invalid prefix for namespace '$ns': '$prefix'\n" unless $prefix =~ /[a-zA-Z][-.a-zA-Z0-9]+/; die "prefix '$prefix' already used by namespace '$self->{'_xml_prefix2ns'}{$prefix}'\n" if exists $self->{'_xml_prefix2ns'}{$prefix}; $self->{'_xml_prefix2ns'}{$prefix} = $ns; $self->{'_xml_ns2prefix'}{$ns} = $prefix; } return; } sub _build_dtd { my $self = $_[0]; $self->{'_xml_elements'} = {}; my $elements_spec = $self->elements_spec(); while ( my ( $elmnt, $spec ) = each %{$elements_spec} ) { $spec = { 'content' => $spec } if ref $spec eq 'ARRAY'; my ( $prefix, $name ) = _parse_xml_name( $elmnt ); die "prefix '$prefix' isn't defined by namespaces()\n" if $prefix && ! exists $self->{'_xml_prefix2ns'}{$prefix}; my $ns = $prefix ? $self->{'_xml_prefix2ns'}{$prefix} : ''; $self->{'_xml_elements'}{$elmnt} = { 'content' => {}, 'start' => undef, 'end' => undef, 'char' => undef, 'expat_name' => $self->{'_xml_expat'}->generate_ns_name( $name, $ns ) }; $spec->{'content'} ||= []; foreach my $ok ( @{$spec->{'content'}} ) { die "element '$ok' used in content of '$elmnt' isn't defined by elements_spec()\n" unless exists $elements_spec->{$ok} || $ok eq 'PCDATA'; $self->{'_xml_elements'}{$elmnt}{'content'}{$ok} = 1; } $self->{'_xml_elements'}{$elmnt}{'start'} = $self->_find_handler( $spec->{'start'}, _default_handler_name( $name, '_start' ) ); $self->{'_xml_elements'}{$elmnt}{'end'} = $self->_find_handler( $spec->{'end'}, _default_handler_name( $name, '_end' ) ); $self->{'_xml_elements'}{$elmnt}{'char'} = $self->_find_handler( $spec->{'char'}, _default_handler_name( $name, '_char' ) ) if exists $self->{'_xml_elements'}{$elmnt}{'content'}{'PCDATA'}; } return; } sub _find_handler { my ( $self, $spec, $default ) = @_; if ( $spec ) { return $spec if ref $spec eq 'CODE'; my $handler = $self->can( $spec ); die "no handler '$spec' defined in ", ref $self, "\n" unless $handler; return $handler; } else { return $self->can( $default ); } } sub _prefixed_name { my ( $self, $name ) = @_; return undef unless defined $name; my $ns = $self->{'_xml_expat'}->namespace( $name ); return $name unless $ns; die "namespace '$ns' wasn't defined by namespaces\n" unless exists $self->{'_xml_ns2prefix'}{$ns}; return $self->{'_xml_ns2prefix'}{$ns} . ":" . $name; } sub _parse_xml_name { return $_[0] =~ /^(?:([a-zA-Z][-.a-zA-Z0-9]+):)?([a-zA-Z][-.a-zA-Z0-9]+)$/; } sub _default_handler_name { my ( $name, $suffix ) = @_; $name =~ tr/a-zA-Z0-9_/_/cs; return $name . $suffix; } =pod =head1 CLIENT METHODS =head2 parse( $xml ) Parse the XML and returns the result. $xml can either be a string or a reference to an open filehandle or IO::Handle object. =cut sub parse { my ( $self, $xml ) = @_; check_param( $xml, 'xml' ); my $parser = new XML::Parser( 'Handlers' => { 'Init' => \&Init, 'Final' => \&Final, 'Start' => \&Start, 'End' => \&End, 'Char' => \&Char, }, 'Namespaces' => 1, 'NoLWP' => 1, ); $parser->{'_LireXMLParser'} = $self; return $parser->parse( $xml ); } =pod =head2 parsefile( $file ) Parses the XML contained in $file and returns the result. =cut sub parsefile { my ( $self, $file ) = @_; check_param( $file, 'file' ); open my $fh, $file or die file_not_readable( $file ); return $self->parse( $fh ); } =pod =head1 META-INFORMATION TEMPLATE METHODS Two template methods must be implemented by subclasses. These methods gives information on the content model of the XML expected by the parser. =head2 namespaces() This method should return an hash reference. The keys are XML namespaces understood by the parser. The value is the prefix which is used for that namespace in the elements_spec() method. =cut sub namespaces { die 'Unimplemented ', ref $_[0], "::namespaces() method\n"; } =pod =head2 elements_spec() This method should return an hash reference. The key are the known XML elements. An error will be thrown by the parser when an element not defined in this hash is encountered. The key should be of the form [ I<prefix> : ] I<element_name>. If prefix is used it should be defined in the namespaces() method. The value of the hash are element specification. This specification can be used to configure the event handlers that will be called as well as specifying the content model of the elements. This specification is an hash reference with the following keys: =over 4 =item content This is an array reference that should contains the name of the elements allowed to appear in that element. These names are in the same format than for the elements_spec() keys. If that element is omitted, the element is considered to be empty and thus cannot contains any other element. If the element can contain PCDATA, the string 'PCDATA' should be listed in the array. =item start This specify the handler called when the opening tag for this element is encountered. This can be either a function reference or a method name. If this element is omitted, the handler will be the method named I<element>_end if it exists, or no handler otherwise. '_' is substituted for invalid method name characters, i.e. report-spec becomes report_spec_start. =item end This specify the handler called when the closing tag for this element is encountered. This can be either a function reference or a method name. If this element is omitted, the handler will be the method named I<element>_end if it exists, or no handler otherwise. '_' is substituted for invalid method name characters, i.e. report-spec becomes report_spec_end. =item char This specify the handler called when PCDATA is encountered within the element. This can only happen if 'PCDATA' appeared in the 'content' attribute. This can be either a function reference or a method name. If this element is omitted, the handler will be the method named I<element>_char if it exists, or no handler otherwise. '_' is substituted for invalid method name characters, i.e. list-item becomes list_item_char. =back The specification can also be an array reference, in that case it will be interpreted as the content of the 'content' hash attribute. Errors will be reported for invalid specification. =cut sub elements_spec { die 'Unimplemented ', ref $_[0], "::element_specs\n"; } =pod =head1 UTILITY METHODS =head2 expat() During the parse, this returns the underlying Lire::XMLParser::Expat parser object. =cut sub expat { return $_[0]{'_xml_expat'}; } =pod =head2 error( $msg ) Will terminate parsing with error message $msg. The current parsing context will be appended to the message. =cut sub error { $_[0]{'_xml_expat'}->xpcroak( $_[1] ); return; } =pod =head2 warning( $msg ) Will print a warning message $msg. The current parsing context will be appended to the message. =cut sub warning { $_[0]{'_xml_expat'}->xpcarp( $_[1] ); return; } =pod =head2 context() Returns as an array reference the names of the currently opened elements. In start and end tag, the last element will be the tag of the parent element. The name of the elements will be in the same format than the one used by elements_spec(). =cut sub context { return [ map { $_[0]->_prefixed_name( $_ ) } $_[0]{'_xml_expat'}->context() ]; } =pod =head2 current_element() Returns the name of the innermost currently opened element. In start and end tag, the last element will be the tag of the parent element. The name of the elements will be in the same format than the one used by elements_spec(). =cut sub current_element { return $_[0]->_prefixed_name( $_[0]{'_xml_expat'}->current_element() ); } =pod =head2 in_element( $element_name ) This returns true if the innermost currently opened element has the same name as $element_name. $element_name should be one of the elements defined by elements_spec(), otherwise the method will croak. Example: if ( $self->in_element( "lire:report") ) { # Parent element is a Lire report element. } elsif ( $self->in_element( "listitem" ) ) { # We are in a DocBook listitem element } =cut sub in_element { my ( $self, $name ) = @_; check_param( $name, 'name' ); $self->error( "no element '$name' defined by elements_spec()" ) unless exists $self->{'_xml_elements'}{$name}; return $self->{'_xml_expat'}->in_element( $self->{'_xml_elements'}{$name}{'expat_name'} ); } =pod =head2 within_element( $element_name ) This returns the number of times an element is opened in the current element ancestor. Like for the in_element(), the element's name should have been defined by elements_spec(), otherwise the method will croak. =cut sub within_element { my ( $self, $name ) = @_; check_param( $name, 'name' ); $self->error( "no element '$name' defined by elements_spec()" ) unless exists $self->{'_xml_elements'}{$name}; return $self->{'_xml_expat'}->within_element( $self->{'_xml_elements'}{$name}{'expat_name'} ); } =pod =head2 recognized_string() Returns the string that trigger the current event. =cut sub recognized_string { return $_[0]{'_xml_expat'}->recognized_string(); } =pod =head2 depth() Returns the number of opened and not yet closed elements. In start and end handlers, the current elemnt is part of that list. =cut sub depth { return $_[0]{'_xml_expat'}->depth(); } =pod =head1 EVENT HANDLERS METHODS These are methods that are called during the XML parsing. =cut =pod =head2 parse_start() This methods is invoked once before the document is parsed. It can be used for any initialization the processor has to do. Default implementation does nothing. =cut sub parse_start {} =pod =head2 parse_end( ) This methods is invoked once after all the XML file was processed. The value that this method returns will be returned by the parse() or parsefile() method (whichever was used to start the parsing). Default implementation does nothing. =cut sub parse_end {} =pod =head2 element_start( $name, $attributes ) Called when a valid element is opened. $name contains the name of the element. This name is the canonical form, that is that if the element is within a namespace, it will be prefixed with the prefix declared by the namespaces() method. $attributes contains the defined attributes in an hash reference. The default method will dispatch to the handlers defined by elements_spec(). =cut sub element_start { my ( $self, $name, $attributes ) = @_; my $handler = $self->{'_xml_elements'}{$name}{'start'}; $handler->( $self, $name, $attributes ) if $handler; return; } =pod =head2 element_end( $name ) Called when a valid element is closed. $name contains the name of the element. Default implementation dispatch to the handler defined by elements_spec(). =cut sub element_end { my ( $self, $name ) = @_; my $handler = $self->{'_xml_elements'}{$name}{'end'}; $handler->( $self, $name ) if $handler; return; } =pod =head2 pcdata( $text ) Called when parsed character data are encountered in an element which is allowed to contain PCDATA. Default implementation dispatch to the handler defined by elements_spec(). =cut sub pcdata { my ( $self, $text ) = @_; my $name = $self->current_element(); my $handler = $self->{'_xml_elements'}{$name}{'char'}; $handler->( $self, $text ) if $handler; return; } =pod =head2 ignorable_ws( $ws ) Called when whitespace is encountered while processing an element which cannot contain PCDATA. Default implementation does nothing. This is mainly used by parser which want to keep the user's format. =cut sub ignorable_ws { my ( $self, $ws ) = @_; return; } =pod =head1 HELPERS METHODS Two common tasks when writing event-based parsers is to use "stacks" and "collectors". The XMLParser object offers some method to manage these common objects. =head2 init_collector( $name ) This initialize a collector with the name $name. If there was already a collector defined under this name, its content will be reset to the empty string ''. =cut sub init_collector { my ( $self, $name ) = @_; check_param( $name, 'name' ); $self->{'_xml_collectors'}{$name} = ''; return; } =pod =head2 collect( $name, $text ) Appends $text to the collector $name. An exception will be thrown if no collector $name was previously defined. =cut sub collect { my ( $self, $name, $text ) = @_; check_param( $name, 'name' ); check_param( $text, 'text' ); $self->error( "no collector '$name' defined" ) unless exists $self->{'_xml_collectors'}{$name}; $self->{'_xml_collectors'}{$name} .= $text; return; } =pod =head2 get_collector( $name ) Returns the content accumulated in the collector $name. An exception will be thrown if no collector $name was previously defined. =cut sub get_collector { my ( $self, $name ) = @_; check_param( $name, 'name' ); $self->error( "no collector '$name' defined" ) unless exists $self->{'_xml_collectors'}{$name}; return $self->{'_xml_collectors'}{$name}; } =pod =head2 collector_start( $element, $attributes ) This is a method which can be used as a start event handler. It will define a collector with the same name than the element which is started. =cut sub collector_start { my ( $self, $element, $attributes ) = @_; $self->init_collector( $element ); return; } =pod =head2 collector_char( $text ) This is a method which can be used as a char event handler. It will append $text to the collector named under the element in which this text occurs. =cut sub collector_char { my ( $self, $text ) = @_; $self->collect( $self->current_element(), $text ); return; } =pod =head2 init_stack( $name ) Initialize a stack object named $name. =cut sub init_stack { my ( $self, $name ) = @_; check_param( $name, 'name' ); $self->{'_xml_stacks'}{$name} = []; return; } =pod =head2 stack_push( $name, $value ) Returns true if the stack $name is empty. An exception will be raise if no stack $name was defined. =cut sub is_stack_empty { my ( $self, $name ) = @_; check_param( $name, 'name' ); $self->error( "no stack '$name' defined" ) unless exists $self->{'_xml_stacks'}{$name}; return @{$self->{'_xml_stacks'}{$name}} == 0; } =pod =head2 stack_depth( $name ) Returns the number of element on the stack $name. An exception will be raise if no stack $name was defined. =cut sub stack_depth { my ( $self, $name ) = @_; check_param( $name, 'name' ); $self->error( "no stack '$name' defined" ) unless exists $self->{'_xml_stacks'}{$name}; return scalar @{$self->{'_xml_stacks'}{$name}}; } =pod =head2 stack_push( $name, $value ) Pushes $value onto the stack $name. An exception will be raise if no stack $name was defined. =cut sub stack_push { my ( $self, $name, $value ) = @_; check_param( $name, 'name' ); $self->error( "no stack '$name' defined" ) unless exists $self->{'_xml_stacks'}{$name}; push @{$self->{'_xml_stacks'}{$name}}, $value; return; } =pod =head2 stack_pop( $name ) Removes and returns the top value on the stack $name. An exception will be raised if no stack $name was defined or if the stack is empty. =cut sub stack_pop { my ( $self, $name ) = @_; check_param( $name, 'name' ); $self->error( "no stack '$name' defined" ) unless exists $self->{'_xml_stacks'}{$name}; $self->error( "stack '$name' is empty" ) unless @{$self->{'_xml_stacks'}{$name}}; return pop @{$self->{'_xml_stacks'}{$name}}; } =pod =head2 stack_peek( $name ) Returns the top value of the stack $name. An exception will be raised if no stack $name was defined or if the stack is empty. =cut sub stack_peek { my ( $self, $name ) = @_; check_param( $name, 'name' ); $self->error( "no stack '$name' defined" ) unless exists $self->{'_xml_stacks'}{$name}; $self->error( "stack '$name' is empty" ) unless @{$self->{'_xml_stacks'}{$name}}; return ${$self->{'_xml_stacks'}{$name}}[-1]; } 1; __END__ =pod =head1 SEE ALSO Lire::Config::SpecParser(3pm), Lire::ReportParser(3pm), Lire::XMLSpecContainer(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: XMLParser.pm,v 1.11 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/DlfAnalyser.pm��������������������������������������������������������������0000644�0001750�0001750�00000005615�10460673254�014360� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::DlfAnalyser; use strict; use base qw/Lire::Plugin/; use Carp; =pod =head1 NAME Lire::DlfAnalyser - Base interface for all DLF analysers. =head1 SYNOPSIS use base qw/ Lire::DlfAnalyser /; =head1 DESCRIPTION This package defines the interface that must be implemented by all DLF Analysers. All the methods defined in this package will throw a 'method not implemented' exception if they are called. Analyser which produce DLF records for an extended schema should probably use the simpler Lire::DlfCategoriser interface. =head1 META INFORMATION METHODS These methods provides information to the Lire framework about the DLF analysers. The Lire::DlfAnalyser interface extends the Lire::Plugin interface, so they must implement all standard meta-information methods (name(), title(), description()). =pod =head2 src_schema() Returns the Dlf schema which is analysed by this analyser. E.g. C<www> =cut sub src_schema { croak "src_schema() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 dst_schema() Returns the Dlf schema which is producted by this analyser. E.g. C<www-user_session> =cut sub dst_schema { croak "dst_schema() not implemented by ", ref $_[0] || $_[0]; } sub type { return 'dlf_analyser' } =head1 IMPLEMENTATION METHOD The analyser does its job using the analyse() method. =head2 analyse( $process, $config ) The $process parameter contains the Lire::DlfAnalyserProcess object which is controlling the conversion process. The $config parameter contains configuration data that was specified in the AnalysisJob for that converter. To register configuration specification for you DlfAnalyser, you just need to define a configuration specification under the name I<analyser_name>_properties. This should be either a RecordSpec or ObjectSpec. =cut sub analyse { croak "analyse() not implemented by ", ref $_[0] || $_[0]; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfAnalyserProcess(3pm), Lire::DlfStore(3pm), Lire::PluginManager(3pm), Lire::DlfCategoriser(3pm). =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: DlfAnalyser.pm,v 1.4 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/DocBookParser.pm������������������������������������������������������������0000644�0001750�0001750�00000021016�10460673255�014643� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::DocBookParser; use strict; use base qw/Lire::XMLParser/; =pod =head1 NAME Lire::XMLParser - Base DocBook parser. =head1 SYNOPSIS package MyParser; use base qw/ Lire::XMLParser /; =head1 DESCRIPTION This package contains a Lire::XMLParser DocBook parser. It defines the relevant C<_start>, C<_end> and C<_char> methods for the DocBook subset used by Lire. All defined handlers have the form C<dbk_I<name>_start>, C<dbk_I<name>_end> and C<dbk_I<name>_char> (when the element accepts PCDATA content). Its base functionality is to collect the DocBook markup for later use. It will subclassed most of the time. =pod =head1 CLIENT METHODS =head2 dbk_init() Subclasses should call this method whenever the state of the DocBook parse should start. This is called from the parse_start() method when the parser is used standalone. =cut sub dbk_init { $_[0]->init_collector( 'docbook' ); $_[0]->{'_dbk_processing'} = 1; return; } =pod =head2 dbk_string() Returns the DocBook XML accumulated by the parser. This is returned from parse_end() method when used standalone. =cut sub dbk_string { $_[0]->{'_dbk_processing'} = 0; return $_[0]->get_collector( 'docbook' ); }; =pod =head1 XML SPECIFICATIONS METHODS IMPLEMENTATION =head2 namespaces() DocBook doesn't use namespace, so this method returns an empty hash reference. =cut sub namespaces { return{}; } =pod =head2 elements_spec() Returns the elements specification for the DocBook subset supported by Lire. =cut our @gen_char_mix = qw/ PCDATA abbrev acronym emphasis foreignphrase phrase quote trademark wordasword action application classname methodname interfacename exceptionname ooclass oointerface ooexception command computeroutput database email envar errorcode errorname errortype errortext filename function guibutton guiicon guilabel guimenu guimenuitem guisubmenu hardware interface keycap keycode keycombo keysym literal constantmarkup menuchoice mousebutton option optional parameter prompt property replaceable returnvalue sgmltag structfield structname symbol systemitem token type userinput varname nonterminal productname productnumber subscript superscript constant markup /; our @inline_mix = ( @gen_char_mix, 'ulink', 'replaceable' ); our @lists_mix = qw/orderedlist itemizedlist variablelist/; our @var_char_mix = qw/PCDATA replaceable/; our @admonitions_mix = qw/caution warning note tip important /; our @top_levels = ( 'para', @Lire::DocBookParser::admonitions_mix, @Lire::DocBookParser::lists_mix ); my %content_models = ( # Inline elements 'abbrev' => [ 'PCDATA' ], 'acronym' => [ 'PCDATA' ], 'emphasis' => [ @inline_mix ], 'foreignphrase' => [ @inline_mix ], 'phrase' => [ @inline_mix ], 'quote' => [ @inline_mix ], 'trademark' => [ 'PCDATA' ], 'wordasword' => [ 'PCDATA' ], 'action' => [ @var_char_mix ], 'application' => [ @var_char_mix ], 'classname' => [ @var_char_mix ], 'constant' => [ @var_char_mix ], 'markup' => [ @var_char_mix ], 'methodname' => [ @var_char_mix ], 'interfacename' => [ @var_char_mix ], 'exceptionname' => [ @var_char_mix ], 'ooclass' => [ @var_char_mix ], 'oointerface' => [ @var_char_mix ], 'ooexception' => [ @var_char_mix ], 'command' => [ @var_char_mix ], 'computeroutput' => [ @var_char_mix ], 'database' => [ @var_char_mix ], 'email' => [ @var_char_mix ], 'envar' => [ @var_char_mix ], 'errorcode' => [ @var_char_mix ], 'errorname' => [ @var_char_mix ], 'errortype' => [ @var_char_mix ], 'errortext' => [ @var_char_mix ], 'filename' => [ @var_char_mix ], 'function' => [ @var_char_mix ], 'guibutton' => [ @var_char_mix ], 'guiicon' => [ @var_char_mix ], 'guilabel' => [ @var_char_mix ], 'guimenu' => [ @var_char_mix ], 'guimenuitem' => [ @var_char_mix ], 'guisubmenu' => [ @var_char_mix], 'hardware' => [ @var_char_mix ], 'interface' => [ @var_char_mix ], 'keycap' => [ @var_char_mix ], 'keycode' => [ @var_char_mix ], 'keycombo' => [ @var_char_mix ], 'keysym' => [ @var_char_mix ], 'literal' => [ @var_char_mix ], 'constantmarkup' => [ @var_char_mix ], 'menuchoice' => [ @var_char_mix ], 'mousebutton' => [ @var_char_mix ], 'option' => [ @var_char_mix ], 'optional' => [ @inline_mix ], 'parameter' => [ @var_char_mix], 'prompt' => [ @var_char_mix ], 'property' => [ @var_char_mix ], 'replaceable' => [ 'PCDATA' ], 'returnvalue' => [ @var_char_mix ], 'sgmltag' => [ @var_char_mix ], 'structfield' => [ @var_char_mix ], 'structname' => [ @var_char_mix ], 'symbol' => [ @var_char_mix ], 'systemitem' => [ @var_char_mix ], 'token' => [ @var_char_mix ], 'type' => [ @var_char_mix ], 'userinput' => [ @var_char_mix ], 'varname' => [ @var_char_mix ], 'nonterminal' => [ @var_char_mix ], 'productname' => [ @var_char_mix ], 'productnumber' => [ @var_char_mix ], 'subscript' => [ @var_char_mix ], 'superscript' => [ @var_char_mix ], 'trademark' => [ @var_char_mix ], # Para 'para' => [ @inline_mix, @lists_mix, @admonitions_mix ], # Special 'ulink' => [ @inline_mix ], 'title' => [ @inline_mix ], 'listitem' => [ 'para', @lists_mix, @admonitions_mix ], 'varlistentry' => [ 'term', 'listitem' ], 'term' => [ @inline_mix ], # Lists 'orderedlist' => [ 'title', @admonitions_mix, 'para', 'listitem' ], 'itemizedlist' => [ 'title', @admonitions_mix, 'para', 'listitem' ], 'variablelist' => [ 'title', @admonitions_mix, 'para', 'varlistentry' ], # Admonitions 'caution' => [ 'title', 'para', @lists_mix, @admonitions_mix ], 'important' => [ 'title', 'para', @lists_mix, @admonitions_mix ], 'note' => [ 'title', 'para', @lists_mix, @admonitions_mix ], 'tip' => [ 'title', 'para', @lists_mix, @admonitions_mix ], 'warning' => [ 'title', 'para', @lists_mix, @admonitions_mix ], ); my $spec = {}; while ( my ( $name, $content ) = each %content_models ) { my $s = { 'start' => "dbk_${name}_start", 'end' => "dbk_${name}_end", 'content' => $content }; $s->{'char'} = "dbk_${name}_char" if ( grep { $_ eq 'PCDATA' } @$content ); $spec->{$name} = $s; no strict 'refs'; while ( my ($name, $content) = each %$spec ) { *{"dbk_${name}_start"} = \&dbk_element_start; *{"dbk_${name}_char"} = \&dbk_element_char if defined $s->{'char'}; *{"dbk_${name}_end"} = \&dbk_element_end; } } sub elements_spec { return { %$spec }; } sub dbk_element_start { my ( $self, $element, $attributes ) = @_; $self->collect( 'docbook', $self->recognized_string() ); return; } sub dbk_element_end { my ( $self, $element ) = @_; $self->collect( 'docbook', $self->recognized_string() ); return; } sub dbk_element_char { my ( $self, $text ) = @_; $self->collect( 'docbook', $self->recognized_string() ); return; } sub ignorable_ws { my ( $self, $text ) = @_; $self->collect( 'docbook', $self->recognized_string() ) if $self->{'_dbk_processing'}; return; } sub parse_start { $_[0]->dbk_init(); return; } sub parse_end { return $_[0]->dbk_string(); } 1; __END__ =pod =head1 SEE ALSO Lire::XMLParser(3pm), Lire::ReportParser::AsciiDocBookFormatter(3pm), Lire::ReportParser::HtmlDocBookFormatter(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: DocBookParser.pm,v 1.4 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/�����������������������������������������������������������������0000755�0001750�0001750�00000000000�11677607767�013776� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_scat_init�����������������������������������������������������0000644�0001750�0001750�00000000253�10460672575�016270� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::ChartTypes::Scat; Lire::PluginManager->register_plugin( new Lire::ChartTypes::Scat() ); �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_stack.xml�����������������������������������������������������0000644�0001750�0001750�00000003222�10460672575�016216� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.1//EN" "http://www.logreport.org/LRCSML/1.1/lrcsml.dtd"> <lrcsml:config-spec xmlns:lrcsml="http://www.logreport.org/LRCSML/" xmlns:lrcml="http://www.logreport.org/LRCML/"> <lrcsml:record name="stack_properties"> <lrcsml:boolean name="stackarea"> <lrcsml:summary>Areas</lrcsml:summary> <lrcsml:description> <para>Plot stacked areas instead of bars.</para> </lrcsml:description> <lrcml:param name="stackarea" value="0"/> </lrcsml:boolean> <lrcsml:reference name="y" index="numerical_variables" required="1"> <lrcsml:summary>First Y Variable</lrcsml:summary> <lrcsml:description> <para>Select the variable which represents the first component of the stack.</para> </lrcsml:description> </lrcsml:reference> <lrcsml:reference name="y2" index="numerical_variables" required="0"> <lrcsml:summary>Second Y Variable</lrcsml:summary> <lrcsml:description> <para>Select a second variable to stack.</para> </lrcsml:description> </lrcsml:reference> <lrcsml:reference name="y3" index="numerical_variables" required="0"> <lrcsml:summary>Third Y Variable</lrcsml:summary> <lrcsml:description> <para>Select a third variable to stack.</para> </lrcsml:description> </lrcsml:reference> <lrcsml:reference name="y4" index="numerical_variables" required="0"> <lrcsml:summary>Fourth Y Variable</lrcsml:summary> <lrcsml:description> <para>Select a fourth variable to stack.</para> </lrcsml:description> </lrcsml:reference> </lrcsml:record> </lrcsml:config-spec> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_vbars.xml�����������������������������������������������������0000644�0001750�0001750�00000002311�10460672575�016224� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.1//EN" "http://www.logreport.org/LRCSML/1.1/lrcsml.dtd"> <lrcsml:config-spec xmlns:lrcsml="http://www.logreport.org/LRCSML/" xmlns:lrcml="http://www.logreport.org/LRCML/"> <lrcsml:record name="vbars_properties"> <lrcsml:boolean name="numbers"> <lrcsml:summary>Plot numbers</lrcsml:summary> <lrcsml:description> <para>Plot the y number above the bars?</para> </lrcsml:description> <lrcml:param name="numbers" value="0"/> </lrcsml:boolean> <lrcsml:reference name="y" index="numerical_variables" required="1"> <lrcsml:summary>First Y Variable</lrcsml:summary> <lrcsml:description> <para>Select the variable which represents the height of the first bar.</para> </lrcsml:description> </lrcsml:reference> <lrcsml:reference name="y2" index="numerical_variables" required="0"> <lrcsml:summary>Second Y Variable</lrcsml:summary> <lrcsml:description> <para>Select optionally a variable which represents the height of a second bar.</para> </lrcsml:description> </lrcsml:reference> </lrcsml:record> </lrcsml:config-spec> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/Pie.pm�����������������������������������������������������������0000644�0001750�0001750�00000003565�10460673256�014763� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ChartTypes::Pie; use strict; use base qw/Lire::ChartType/; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::ChartTypes::Pie - Wrapper for the Ploticus pie prefab. =head1 SYNOPSIS my $type = $chart_cfg->get( 'type' )->as_value(); $type->write_chart( $chart_cfg, $subreport ); =head1 DESCRIPTION This Lire::ChartType wraps the Ploticus pie prefab. =cut sub name { return 'pie'; } sub title { return 'Pie chart'; } sub description { return '<para>' . __( 'Pie chart' ) . '</para>'; } sub prefab { return '-prefab pie' } sub get_vars { my ( $self, $chart_cfg ) = @_; return [ $chart_cfg->get( 'type' )->get_properties()->get( 'values' )->as_value() ]; } sub write_parameters { my ( $self, $chart_cfg, $fh ) = @_; $self->SUPER::write_parameters( $chart_cfg, $fh ); print $fh <<EOF; #set labels = 1 #set values = 2 EOF return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::ChartType(3pm), ploticus(1) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Pie.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_lines.xml�����������������������������������������������������0000644�0001750�0001750�00000003740�10460672575�016230� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.1//EN" "http://www.logreport.org/LRCSML/1.1/lrcsml.dtd"> <lrcsml:config-spec xmlns:lrcsml="http://www.logreport.org/LRCSML/" xmlns:lrcml="http://www.logreport.org/LRCML/"> <lrcsml:record name="lines_properties"> <lrcsml:boolean name="numbers"> <lrcsml:summary>Plot numbers</lrcsml:summary> <lrcsml:description> <para>Plot the y number beside the points?</para> </lrcsml:description> <lrcml:param name="numbers" value="0"/> </lrcsml:boolean> <lrcsml:reference name="x" index="numerical_variables" required="0"> <lrcsml:summary>Numerical X Variable</lrcsml:summary> <lrcsml:description> <para>If you select a numerical variable here, it will be used for the X axis instead of the 'case_var' variable. </para> </lrcsml:description> </lrcsml:reference> <lrcsml:reference name="y" index="numerical_variables" required="1"> <lrcsml:summary>First Y Variable</lrcsml:summary> <lrcsml:description> <para>Select the variable which represents the Y component of the points. </para> </lrcsml:description> </lrcsml:reference> <lrcsml:reference name="y2" index="numerical_variables" required="0"> <lrcsml:summary>Second Y Variable</lrcsml:summary> <lrcsml:description> <para>Select a second variable to plot.</para> </lrcsml:description> </lrcsml:reference> <lrcsml:reference name="y3" index="numerical_variables" required="0"> <lrcsml:summary>Third Y Variable</lrcsml:summary> <lrcsml:description> <para>Select a third variable to plot.</para> </lrcsml:description> </lrcsml:reference> <lrcsml:reference name="y4" index="numerical_variables" required="0"> <lrcsml:summary>Fourth Y Variable</lrcsml:summary> <lrcsml:description> <para>Select a fourth variable to plot.</para> </lrcsml:description> </lrcsml:reference> </lrcsml:record> </lrcsml:config-spec> ��������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_scat.xml������������������������������������������������������0000644�0001750�0001750�00000002672�10460672575�016053� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.1//EN" "http://www.logreport.org/LRCSML/1.1/lrcsml.dtd"> <lrcsml:config-spec xmlns:lrcsml="http://www.logreport.org/LRCSML/" xmlns:lrcml="http://www.logreport.org/LRCML/"> <lrcsml:record name="scat_properties"> <lrcsml:reference name="x" index="numerical_variables"> <lrcsml:summary>X component</lrcsml:summary> <lrcsml:description> <para>Select the variable which represents the X components of the points. </para> </lrcsml:description> </lrcsml:reference> <lrcsml:reference name="y" index="numerical_variables"> <lrcsml:summary>Y component</lrcsml:summary> <lrcsml:description> <para>Select the variable which represents the Y component of the points. </para> </lrcsml:description> </lrcsml:reference> <lrcsml:boolean name="label"> <lrcsml:summary>Label points</lrcsml:summary> <lrcsml:description> <para>Controls whether or not the points will be labelled.</para> </lrcsml:description> <lrcml:param name="label" value="0"/> </lrcsml:boolean> <lrcsml:boolean name="corr"> <lrcsml:summary>Regression line</lrcsml:summary> <lrcsml:description> <para>Controls whether or not a regression line will be drawn.</para> </lrcsml:description> <lrcml:param name="corr" value="0"/> </lrcsml:boolean> </lrcsml:record> </lrcsml:config-spec> ����������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_dist.xml������������������������������������������������������0000644�0001750�0001750�00000001735�10460672575�016063� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.1//EN" "http://www.logreport.org/LRCSML/1.1/lrcsml.dtd"> <lrcsml:config-spec xmlns:lrcsml="http://www.logreport.org/LRCSML/" xmlns:lrcml="http://www.logreport.org/LRCML/"> <lrcsml:record name="dist_properties"> <lrcsml:boolean name="curve"> <lrcsml:summary>Distribution curve</lrcsml:summary> <lrcsml:description> <para>Controls whether or not a bspline curve will be drawn over the plot.</para> </lrcsml:description> <lrcml:param name="curve" value="yes"/> </lrcsml:boolean> <lrcsml:reference name="x" index="numerical_variables"> <lrcsml:summary>Variable</lrcsml:summary> <lrcsml:description> <para>Numerical variable for which the distribution will be plotted for the cases selected by 'case_var'. </para> </lrcsml:description> </lrcsml:reference> </lrcsml:record> </lrcsml:config-spec> �����������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/Stack.pm���������������������������������������������������������0000644�0001750�0001750�00000005330�10460673256�015303� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ChartTypes::Stack; use strict; use base qw/Lire::ChartType/; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::ChartTypes::Stack - Wrapper for the Ploticus stack prefab. =head1 SYNOPSIS my $type = $chart_cfg->get( 'type' )->as_value(); $type->write_chart( $chart_cfg, $subreport ); =head1 DESCRIPTION This Lire::ChartType wraps the Ploticus stack prefab. =cut sub name { return 'stack'; } sub title { return 'Stack chart'; } sub description { return '<para>' . __( 'Plot one to four variable stacked one over the other.' ) . '</para>'; } sub prefab { return '-prefab stack' } sub get_vars { my ( $self, $chart_cfg ) = @_; my @vars = (); my $props = $chart_cfg->get('type')->get_properties(); push @vars, $props->get( 'y' )->as_value(); push @vars, $props->get( 'y2' )->as_value() if $props->get( 'y2' )->is_valid(); push @vars, $props->get( 'y3' )->as_value() if $props->get( 'y3' )->is_valid(); push @vars, $props->get( 'y4' )->as_value() if $props->get( 'y4' )->is_valid(); return \@vars; } sub write_parameters { my ( $self, $chart_cfg, $fh ) = @_; $self->SUPER::write_parameters( $chart_cfg, $fh ); my $props = $chart_cfg->get('type')->get_properties(); my $idx = 2; my $stackarea = ( $props->get( 'stackarea' )->as_value() ? 'yes' : 'no' ); print $fh "#set stubvert = yes\n#set stackarea = $stackarea\n"; print $fh "#set y = ", $idx++, "\n"; print $fh "#set y2 = ", $idx++, "\n" if $props->get( 'y2' )->is_valid(); print $fh "#set y3 = ", $idx++, "\n" if $props->get( 'y3' )->is_valid(); print $fh "#set y4 = ", $idx++, "\n" if $props->get( 'y4' )->is_valid(); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::ChartType(3pm), ploticus(1) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Stack.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_pie_init������������������������������������������������������0000644�0001750�0001750�00000000251�10460672575�016111� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::ChartTypes::Pie; Lire::PluginManager->register_plugin( new Lire::ChartTypes::Pie() ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/Dist.pm����������������������������������������������������������0000644�0001750�0001750�00000003747�10460673256�015153� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ChartTypes::Dist; use strict; use base qw/Lire::ChartType/; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::ChartTypes::Dist - Wrapper for the Ploticus dist prefab. =head1 SYNOPSIS my $type = $chart_cfg->get( 'type' )->as_value(); $type->write_chart( $chart_cfg, $subreport ); =head1 DESCRIPTION This Lire::ChartType wraps the Ploticus dist prefab. =cut sub name { return 'dist'; } sub title { return 'Distribution chart'; } sub description { return '<para>' . __( 'Distribution chart' ) . '</para>'; } sub prefab { return '-prefab dist' } sub get_vars { my ( $self, $chart_cfg ) = @_; return [ $chart_cfg->get( 'type' )->get_properties()->get( 'x' )->as_value() ]; } sub write_parameters { my ( $self, $chart_cfg, $fh ) = @_; $self->SUPER::write_parameters( $chart_cfg, $fh ); my $curve = ( $chart_cfg->type_properties()->get( 'curve' )->as_value() ? 'yes' : 'no' ); print $fh <<EOF; #set x = 2 #set curve = $curve EOF return; } 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::ChartType(3pm), ploticus(1) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Dist.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������lire-2.1.1/all/lib/Lire/ChartTypes/Makefile.am������������������������������������������������������0000644�0001750�0001750�00000003406�10077767532�015743� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.6 2004/07/22 16:46:18 flacoste Exp $ ## Copyright (C) 2000-2001 Stichting LogReport Foundation LogReport@LogReport.org ## ## This file is part of Lire. ## ## Lire is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk specdir = $(datadir)/$(PACKAGE)/config-spec spec_DATA = \ ct_dist.xml \ ct_lines.xml \ ct_pie.xml \ ct_scat.xml \ ct_stack.xml \ ct_vbars.xml pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins plugins_DATA = \ ct_dist_init \ ct_lines_init \ ct_pie_init \ ct_scat_init \ ct_stack_init \ ct_vbars_init allperllibdir = $(LR_PERL5LIBDIR)/Lire/ChartTypes pm_s = \ Dist.pm \ Lines.pm \ Pie.pm \ Scat.pm \ Stack.pm \ VBars.pm allperllib_DATA = $(pm_s) man_MANS = \ Dist.3pm \ Lines.3pm \ Pie.3pm \ Scat.3pm \ Stack.3pm \ VBars.3pm perlpackage = Lire::ChartTypes transform = s,^,$(perlpackage)::, EXTRA_DIST = $(pm_s) $(spec_DATA) $(plugins_DATA) CLEANFILES = $(man_MANS) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/Makefile.in������������������������������������������������������0000644�0001750�0001750�00000047345�11677606132�015761� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/include/rules.mk subdir = all/lib/Lire/ChartTypes ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" \ "$(DESTDIR)$(pluginsdir)" "$(DESTDIR)$(specdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(allperllib_DATA) $(plugins_DATA) $(spec_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) transform = s,^,$(perlpackage)::, ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done specdir = $(datadir)/$(PACKAGE)/config-spec spec_DATA = \ ct_dist.xml \ ct_lines.xml \ ct_pie.xml \ ct_scat.xml \ ct_stack.xml \ ct_vbars.xml plugins_DATA = \ ct_dist_init \ ct_lines_init \ ct_pie_init \ ct_scat_init \ ct_stack_init \ ct_vbars_init allperllibdir = $(LR_PERL5LIBDIR)/Lire/ChartTypes pm_s = \ Dist.pm \ Lines.pm \ Pie.pm \ Scat.pm \ Stack.pm \ VBars.pm allperllib_DATA = $(pm_s) man_MANS = \ Dist.3pm \ Lines.3pm \ Pie.3pm \ Scat.3pm \ Stack.3pm \ VBars.3pm perlpackage = Lire::ChartTypes EXTRA_DIST = $(pm_s) $(spec_DATA) $(plugins_DATA) CLEANFILES = $(man_MANS) all: all-am .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/Lire/ChartTypes/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/Lire/ChartTypes/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man3: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list=''; test -n "$(man3dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } install-allperllibDATA: $(allperllib_DATA) @$(NORMAL_INSTALL) test -z "$(allperllibdir)" || $(MKDIR_P) "$(DESTDIR)$(allperllibdir)" @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(allperllibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(allperllibdir)" || exit $$?; \ done uninstall-allperllibDATA: @$(NORMAL_UNINSTALL) @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(allperllibdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(allperllibdir)" && rm -f $$files install-pluginsDATA: $(plugins_DATA) @$(NORMAL_INSTALL) test -z "$(pluginsdir)" || $(MKDIR_P) "$(DESTDIR)$(pluginsdir)" @list='$(plugins_DATA)'; test -n "$(pluginsdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pluginsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pluginsdir)" || exit $$?; \ done uninstall-pluginsDATA: @$(NORMAL_UNINSTALL) @list='$(plugins_DATA)'; test -n "$(pluginsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(pluginsdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(pluginsdir)" && rm -f $$files install-specDATA: $(spec_DATA) @$(NORMAL_INSTALL) test -z "$(specdir)" || $(MKDIR_P) "$(DESTDIR)$(specdir)" @list='$(spec_DATA)'; test -n "$(specdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(specdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(specdir)" || exit $$?; \ done uninstall-specDATA: @$(NORMAL_UNINSTALL) @list='$(spec_DATA)'; test -n "$(specdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(specdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(specdir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" "$(DESTDIR)$(pluginsdir)" "$(DESTDIR)$(specdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-allperllibDATA install-man \ install-pluginsDATA install-specDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man3 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-allperllibDATA uninstall-man \ uninstall-pluginsDATA uninstall-specDATA uninstall-man: uninstall-man3 .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ distclean distclean-generic distdir dvi dvi-am html html-am \ info info-am install install-allperllibDATA install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-man3 \ install-pdf install-pdf-am install-pluginsDATA install-ps \ install-ps-am install-specDATA install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am uninstall uninstall-allperllibDATA \ uninstall-am uninstall-man uninstall-man3 \ uninstall-pluginsDATA uninstall-specDATA .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/Scat.pm����������������������������������������������������������0000644�0001750�0001750�00000005140�10460673256�015127� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ChartTypes::Scat; use strict; use base qw/Lire::ChartType/; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::ChartTypes::Scat - Wrapper for the Ploticus scat prefab. =head1 SYNOPSIS my $type = $chart_cfg->get( 'type' )->as_value(); $type->write_chart( $chart_cfg, $subreport ); =head1 DESCRIPTION This Lire::ChartType wraps the Ploticus scat prefab. =cut sub name { return 'scat'; } sub title { return 'Scat chart'; } sub description { return '<para>' . __( 'Scatterplot of two variables with optional regression line.' ) . '</para>'; } sub prefab { return '-prefab scat' } sub get_vars { my ( $self, $chart_cfg ) = @_; return [ $chart_cfg->type_properties()->get( 'x' )->as_value(), $chart_cfg->type_properties()->get( 'y' )->as_value() ]; } sub write_parameters { my ( $self, $chart_cfg, $fh ) = @_; # We do not link to our parent implemenation print $fh "#set title = ", $chart_cfg->title(), "\n" if $chart_cfg->title(); print $fh "#set name = ", $chart_cfg->case_var()->label(), "\n"; my $props = $chart_cfg->get('type')->get_properties(); my $xlbl = ( $chart_cfg->xlabel() ? $chart_cfg->xlabel() : $props->get( 'x' )->as_value()->label() ); my $ylbl = ( $chart_cfg->ylabel() ? $chart_cfg->ylabel() : $props->get( 'y' )->as_value()->label() ); my $corr = $props->get( 'corr' )->as_value() ? 'yes' : 'no'; print $fh <<EOF; #set x = 2 #set xlbl = $xlbl #set y = 3 #set ylbl = $ylbl #set corr = $corr EOF print $fh "#set id = 1\n" if $props->get( 'label' )->as_value(); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::ChartType(3pm), ploticus(1) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Scat.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_vbars_init����������������������������������������������������0000644�0001750�0001750�00000000255�10460672575�016455� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::ChartTypes::VBars; Lire::PluginManager->register_plugin( new Lire::ChartTypes::VBars() ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_dist_init�����������������������������������������������������0000644�0001750�0001750�00000000253�10460672575�016301� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::ChartTypes::Dist; Lire::PluginManager->register_plugin( new Lire::ChartTypes::Dist() ); �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/Lines.pm���������������������������������������������������������0000644�0001750�0001750�00000005653�10460673256�015320� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ChartTypes::Lines; use strict; use base qw/Lire::ChartType/; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::ChartTypes::Lines - Wrapper for the Ploticus lines prefab. =head1 SYNOPSIS my $type = $chart_cfg->get( 'type' )->as_value(); $type->write_chart( $chart_cfg, $subreport ); =head1 DESCRIPTION This Lire::ChartType wraps the Ploticus lines prefab. =cut sub name { return 'lines'; } sub title { return 'Lines chart'; } sub description { return '<para>' . __( 'Plot one to four variable as lines against another.' ) . '</para>'; } sub prefab { return '-prefab lines' } sub get_vars { my ( $self, $chart_cfg ) = @_; my @vars = (); my $props = $chart_cfg->get('type')->get_properties(); push @vars, $props->get( 'x' )->as_value() if $props->get( 'x' )->is_valid(); push @vars, $props->get( 'y' )->as_value(); push @vars, $props->get( 'y2' )->as_value() if $props->get( 'y2' )->is_valid(); push @vars, $props->get( 'y3' )->as_value() if $props->get( 'y3' )->is_valid(); push @vars, $props->get( 'y4' )->as_value() if $props->get( 'y4' )->is_valid(); return \@vars; } sub write_parameters { my ( $self, $chart_cfg, $fh ) = @_; $self->SUPER::write_parameters( $chart_cfg, $fh ); my $props = $chart_cfg->get('type')->get_properties(); my $idx = 2; if ( $props->get( 'x' )->is_valid() ) { print $fh "#set cats = no\n#set x = ", $idx++, "\n"; } else { print $fh "#set cats = yes\n#set stubvert = yes\n#set legend = max+0.1 max\n"; } print $fh "#set y = ", $idx++, "\n"; print $fh "#set y2 = ", $idx++, "\n" if $props->get( 'y2' )->is_valid(); print $fh "#set y3 = ", $idx++, "\n" if $props->get( 'y3' )->is_valid(); print $fh "#set y4 = ", $idx++, "\n" if $props->get( 'y4' )->is_valid(); print $fh "#set numbers = yes\n" if $props->get( 'numbers' )->as_value(); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::ChartType(3pm), ploticus(1) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Lines.pm,v 1.2 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_pie.xml�������������������������������������������������������0000644�0001750�0001750�00000001262�10460672575�015670� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.1//EN" "http://www.logreport.org/LRCSML/1.1/lrcsml.dtd"> <lrcsml:config-spec xmlns:lrcsml="http://www.logreport.org/LRCSML/" xmlns:lrcml="http://www.logreport.org/LRCML/"> <lrcsml:record name="pie_properties"> <lrcsml:reference name="values" index="numerical_variables"> <lrcsml:summary>Values Variable</lrcsml:summary> <lrcsml:description> <para>The subreport's numerical variable that will be used to compute the pie's areas. </para> </lrcsml:description> </lrcsml:reference> </lrcsml:record> </lrcsml:config-spec> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_lines_init����������������������������������������������������0000644�0001750�0001750�00000000255�10460672575�016452� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::ChartTypes::Lines; Lire::PluginManager->register_plugin( new Lire::ChartTypes::Lines() ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/VBars.pm���������������������������������������������������������0000644�0001750�0001750�00000004445�10460673256�015261� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ChartTypes::VBars; use strict; use base qw/Lire::ChartType/; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::ChartTypes::Lines - Wrapper for the Ploticus vbars prefab. =head1 SYNOPSIS my $type = $chart_cfg->get( 'type' )->as_value(); $type->write_chart( $chart_cfg, $subreport ); =head1 DESCRIPTION This Lire::ChartType wraps the Ploticus vbars prefab. =cut sub name { return 'vbars'; } sub title { return 'Vertical Bars Chart'; } sub description { return '<para>' . __( 'Plot one or two variables as bars.' ) . '</para>'; } sub prefab { return '-prefab vbars' } sub get_vars { my ( $self, $chart_cfg ) = @_; my $props = $chart_cfg->get('type')->get_properties(); my @vars = ( $props->get( 'y' )->as_value() ); push @vars, $props->get( 'y2' )->as_value() if $props->get( 'y2' )->is_valid(); return \@vars; } sub write_parameters { my ( $self, $chart_cfg, $fh ) = @_; $self->SUPER::write_parameters( $chart_cfg, $fh ); my $props = $chart_cfg->get('type')->get_properties(); print $fh <<EOF; #set stubvert = yes #set barwidth = 0.05 #set sep = 0.08 #set y = 2 EOF print $fh "#set y2 = 3\n" if $props->get( 'y2' )->is_valid(); print $fh "#set vals = yes\n" if $props->get( 'numbers' )->as_value(); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::ChartType(3pm), ploticus(1) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: VBars.pm,v 1.3 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ChartTypes/ct_stack_init����������������������������������������������������0000644�0001750�0001750�00000000255�10460672575�016445� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::ChartTypes::Stack; Lire::PluginManager->register_plugin( new Lire::ChartTypes::Stack() ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ImportJob.pm����������������������������������������������������������������0000644�0001750�0001750�00000020136�10460673255�014055� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ImportJob; use strict; use Carp; use POSIX qw/ strftime /; use Lire::Error qw/ file_not_readable /; use Lire::I18N qw/ set_fh_encoding /; use Lire::Utils qw/ check_param check_object_param /; use Lire::DlfConverterProcess; =pod =head1 NAME Lire::ImportJob - Object used to represent an periodical source of log data =head1 SYNOPSIS use Lire::ImportJob; my $src = new Lire::ImportJob( "name", 'pattern' => "/var/log/messsages", 'period' => "unique", 'processor' => $name, ); my $file = $src->file, =head1 DESCRIPTION The Lire::ImportJob object is used to represent a source of log data. ImportJobs can also be instantiated from configuration data (The 'import_job' configuration specification.) =head1 new( $name, ... ); Create a new Lire::ImportJob object. As mandatory parameter, it takes the name of the log source. Additional parameters: =over =item pattern The path to the file that contains the log data. This filename can contain strftime(3) patterns that will be substituted to obtain the name of the file. (Useful for automatic rotation). =item period The periodicity to which this ImportJob should be processed. Defaults to 'unique' which means this is a one-shot ImportJob. Other recognized values are 'hourly', 'daily', 'weekly', 'monthly' and 'yearly'. =item converter The name of the converter that can be used to process the ImportJob. This must be known to the Lire::PluginManager. =item converter_config Configuration parameter for the DlfConverter. =item filter A shell command that will be used to filter the log file. =item encoding Encoding for the log file. If omitted, the default system encoding will be used. =back =cut sub new { my ($pkg, $name, %args) = @_; check_param( $name, 'name' ); $args{'period'} ||= "unique"; my $self = bless { '_name' => $name, '_converter' => undef, '_converer_config' => undef, '_pattern' => undef, '_period' => undef, '_filter' => undef, '_encoding' => undef, }, ref $pkg || $pkg; foreach my $p ( qw/pattern period converter converter_config filter encoding/ ) { no strict 'refs'; $self->$p( $args{$p} ) if exists $args{$p}; } return $self; } =pod =head2 name() Returns the name of this ImportJob. =cut sub name { $_[0]{'_name'} }; =pod =head2 period( [$new_period] ) With no argument, returns the period of this ImportJob. With a parameter, the ImportJob's period is set to this new value. =cut sub period { my ( $self, $period ) = @_; if ( @_ == 2 ) { check_param( $period, 'period', qr/^(unique|hourly|daily|weekly|monthly|yearly)$/, "'period' parameter can only be 'unique', 'daily', 'weekly' or 'monthly'" ); $self->{'_period'} = $period; } $self->{'_period'}; } =pod =head2 file( [$time] ) Returns the file to be used. The optional $time parameter (which defaults to now) is used to compute the file name. To find the file to use for yesterday's data, one could pass time - 86400. =cut sub file { my ( $self, $time ) = @_; $time ||= time; return strftime $self->{'_pattern'}, localtime $time; } =pod =head2 pattern( [$new_file] ) Returns the file pattern to use as log data source. This pattern may contain strftime(3) substitutions. If an argument is used, it will change the file to use. =cut sub pattern { my ( $self, $pattern ) = @_; if ( @_ == 2 ) { check_param( $pattern, 'pattern' ); $self->{'_pattern'} = $pattern; } return $self->{'_pattern'}; } =pod =head2 filter( [$new_filter] ) Returns the shell command that will be used as filter. Undef or '' will not use a filter. =cut sub filter { my ( $self, $filter ) = @_; if ( @_ == 2 ) { $self->{'_filter'} = $filter ? $filter : undef; } return $self->{'_filter'}; } =pod =head2 encoding( [$new_encoding] ) Returns the encoding of the log file. Undef and '' means to use the system default encoding. =cut sub encoding { my ( $self, $encoding ) = @_; if ( @_ == 2 ) { $self->{'_encoding'} = $encoding ? $encoding : undef; } return $self->{'_encoding'}; } =pod =head2 converter( [$new_name] ) Returns the name of the converter that should be used for this ImportJob. =cut sub converter { my ( $self, $converter ) = @_; if ( @_ == 2 ) { check_param( $converter, 'converter' ); $self->{'_converter'} = $converter; } return $self->{'_converter'}; } =pod =head2 converter_config( [$new_config] ) Returns a configuration object that should be used by the DlfConverter (through the set_configuration() method). =cut sub converter_config { my ( $self, $config ) = @_; if ( @_ == 2 ) { $self->{'_converter_config'} = $config; } return $self->{'_converter_config'}; } =pod =head2 log_fh( [ $time ] ) Returns a file handle that can be used to read from the log. $time is the parameter taken by file to determine the final filename. All filters and encoding will be setup properly. =cut sub log_fh { my ( $self, $time ) = @_; my $filename = $self->file( $time ); my $fh; if ( $self->{'_filter'} ) { if ( index( $self->{'_filter'}, '|' ) != -1 ) { $filename = "cat '$filename' | $self->{'_filter'} |" } else { $filename = "$self->{'_filter'} < '$filename' |" } } open $fh, $filename or die file_not_readable( $filename ); set_fh_encoding( $fh, $self->{'_encoding'} ) if $self->{'_encoding'}; return $fh; } =pod =head2 run( $store, [$time] ) Runs this ImportJob and import it into the $store DlfStore. The $time parameter will be used to determine the time window covered by period. It defaults to the current time. =cut sub run { my ( $self, $store, $time ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); my $process = new Lire::DlfConverterProcess( $self, $store ); $process->run_import_job( $time ); my $converter = Lire::PluginManager->get_plugin( 'dlf_converter', $self->{'_converter'} ); foreach my $name ( $converter->schemas() ) { $store->run_analysers( $name, $process->job_id() ) if $store->has_dlf_stream( $name ); } return; } # Used to instantiate from Lire::Config::Object sub new_from_config { my ( $class, $config ) = @_; $config = $config->Lire::Config::Dictionary::as_value(); return new Lire::ImportJob( $config->{'name'}, 'period' => $config->{'period'}, 'encoding' => $config->{'log_encoding'}, 'pattern' => $config->{'log_file'}, 'converter' => $config->{'service'}{'plugin'}, 'converter_config' => $config->{'service'}{'properties'}, 'filter' => $config->{'filter'} ); } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfStore(3pm) Lire::DlfConverter(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: ImportJob.pm,v 1.14 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Last.pm���������������������������������������������������������������������0000644�0001750�0001750�00000015147�10765035043�013054� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Last; use strict; use base qw/ Lire::SimpleStat /; use Carp; use Lire::Utils qw/ sql_quote_name check_object_param /; use Lire::DataTypes qw/ is_numeric_type /; =pod =head1 NAME Lire::Last - Lire class that implements the last operator =head1 SYNOPSIS use Lire::Last =head1 DESCRIPTION Class that implements the last operator. This operator will output the last value appearing in its field when the DLF records are sorted according to the C<sort_fields> attribute. The default sort order is the default timestamp sort. =head1 METHODS =head2 new( %params ) Creates a new Lire::Last object. =cut sub new { my ( $class, %params ) = @_; my $self = bless {}, $class; $self->init( %params, 'op' => 'last' ); $self->sort_fields( $params{'sort_fields'} ); return $self; } #------------------------------------------------------------------------ # Method field( [$field] # # Overrides Lire::SimpleStat one since the field doesn't have # to be numeric. sub field { my ( $self, $field ) = @_; if ( @_ == 2 ) { if ( defined $field ) { croak "'$field' isn't a defined field in the specifcation's schemas" unless $self->report_spec()->has_field( $field ); } $self->{'field'} = $field; } return $self->{'field'}; } =pod =head2 sort_fields( [$new_sort_fields] ) Returns the fields that are going to be used to sort the DLF records. This a reference to an array of DLF field names. If the $new_sort_fields parameter is set, it will be used as the new sort order. It must be an array reference and should only contains valid field names for the current report specification's schema. When no sort_fields are set, the default is to use the default timestamp field. =cut =cut sub sort_fields { my ($self, $sort_fields) = @_; if ( @_ == 2 ) { if ( defined $sort_fields ) { check_object_param( $sort_fields, 'sort_fields', 'ARRAY' ); foreach my $f ( @$sort_fields ) { croak "'$f' isn't a defined field in the specification's schemas" unless $self->report_spec()->has_field( $f ); } } $self->{'sort_fields'} = $sort_fields; } return $self->{'sort_fields'}; } #------------------------------------------------------------------------ # Method xml_attrs() # # Implementation needed by Lire::Aggregate sub xml_attrs { my ($self) = @_; my $attr = $self->SUPER::xml_attrs; if ( exists $self->{'sort_fields'} ) { my $sort_fields = join " ", @{$self->{'sort_fields'}}; $attr .= qq{ sort="$sort_fields"}; } return $attr; } # Overrides Lire::SimpleStat::sql_required_fields sub sql_required_fields { my $self = $_[0]; my @fields = ( $self->{'field'} ); push @fields, @{ $self->{'sort_fields'} } if defined $self->{'sort_fields'}; return \@fields; } # Overrides Lire::Aggregate::build_query sub build_query { my ( $self, $query ) = @_; $self->_build_last_query( $query ); $self->set_missing_cases_aggr_expr( $query ); } sub _build_last_query { my ( $self, $query ) = @_; my @fields = map { sql_quote_name( $_ ) } @{ $self->sql_required_fields()}; $query->add_aggr_field( $self->name(), sprintf( 'lr_last(%s)', join( ",", @fields ))); if ( $self->{'sort_fields'} ) { $query->add_aggr_field( $self->name() . '_key', sprintf( 'lr_last_key(%s)', join( ",", @fields ))); } return; } # Overrides Lire::SimpleStat::create_value sub create_value { my ( $self, $parent_group, $row ) = @_; my $v = $self->SUPER::create_value( $parent_group, $row ); if ( ! is_numeric_type( $self->dlf_field()->type() ) ) { $v->{'content'} = $row->{ $self->name() }; } $v->{'total'} = $row->{ $self->name() . "_key" }; return $v; } # Implements Lire::ReportOperator::init_merge() sub init_merge { my $self = $_[0]; $self->SUPER::init_merge(); my $sort_fields = $self->sort_fields(); unless ( $sort_fields && @$sort_fields ) { $sort_fields = [ $self->report_spec()->schema()->timestamp_field()->name() ]; } my @cmp = (); my $i = 0; foreach my $f ( @$sort_fields ) { my $type = $self->report_spec()->schema()->field( $f )->type(); my $cmp = is_numeric_type( $type ) ? '<=>' : 'cmp'; push @cmp, "\$_[0][$i] $cmp \$_[1][$i]"; $i++; } my $sort_code = "sub { " . join( " && ", @cmp ) . " }"; $self->{'sort_func'} = eval $sort_code; croak "failed to compile sort function ($sort_code): $@" if $@; $self->{'total_func'} = sub { return defined $_[0] ? join( " ", @{$_[0]} ) : ''; }; return; } # Implements Lire::ReportOperator::init_group_data() sub init_group_data { return []; } # Implements Lire::ReportOperator::merge_group_data() sub merge_group_data { my ( $self, $value, $data ) = @_; return unless $value->{'total'}; my $fields = [ split / /, $value->{'total'} ]; unless (defined $data->[0]) { $data->[0] = $value->{'value'}; $data->[1] = $fields; return; } # Change the value only if the fields sorts after the last one if ( $self->{'sort_func'}->( $fields, $data->[1] ) > 0 ) { $data->[0] = $value->{'value'}; $data->[1] = $fields; } return; } # Implements Lire::Aggregate::data2dlf() sub data2dlf { my ($self, $data) = @_; my $name = $self->name(); return { "$name" => $data->[0], "${name}_key" => $self->{'total_func'}->( $data->[1] ), "_lr_${name}_mc" => $self->missing_cases( $data ), }; } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::ReportOperator(3pm), Lire::Aggregator(3pm), Lire::Aggregate(3pm), Lire::First(3pm) =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <wsourdeau@logreport.org> =head1 VERSION $Id: Last.pm,v 1.14 2008/03/09 19:27:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Makefile.am�����������������������������������������������������������������0000644�0001750�0001750�00000006731�10456406627�013655� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.73 2006/07/16 09:57:43 vanbaal Exp $ ## Copyright (C) 2000-2001 Stichting LogReport Foundation LogReport@LogReport.org ## ## This file is part of Lire. ## ## Lire is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk SUBDIRS = ChartTypes OutputFormats Report ReportParser SQLExt Test Config UI allperllibdir = $(LR_PERL5LIBDIR)/Lire pm_s = \ Aggregate.pm \ Aggregator.pm \ Average.pm \ ChartType.pm \ Config.pm \ Count.pm \ DataTypes.pm \ DerivedSchema.pm \ DlfAnalyser.pm \ DlfAnalyserProcess.pm \ DlfCategoriser.pm \ DlfConverter.pm \ DlfConverterProcess.pm \ DlfQuery.pm \ DlfResult.pm \ DlfSchema.pm \ DlfStore.pm \ DlfStream.pm \ DocBookParser.pm \ Error.pm \ ExtendedSchema.pm \ Field.pm \ FilterExpr.pm \ FilterSpec.pm \ First.pm \ Group.pm \ GroupField.pm \ I18N.pm \ ImportJob.pm \ Last.pm \ Logger.pm \ LrCommand.pm \ Max.pm \ Min.pm \ OldDlfAdapter.pm \ OutputFormat.pm \ OutputJob.pm \ Param.pm \ Plugin.pm \ PluginManager.pm \ Program.pm \ Rangegroup.pm \ Records.pm \ Report.pm \ ReportConfig.pm \ ReportJob.pm \ ReportOperator.pm \ ReportParser.pm \ ReportSchedule.pm \ ReportSection.pm \ ReportSpec.pm \ SimpleStat.pm \ Sum.pm \ Syslog.pm \ Time.pm \ Timegroup.pm \ Timeslot.pm \ UI.pm \ Utils.pm \ W3CExtendedLog.pm \ WeekCalculator.pm \ WELF.pm \ XMLParser.pm \ XMLSpecContainer.pm \ XMLSpecI18N.pm \ XMLSpecParser.pm allperllib_DATA = $(pm_s) man_MANS = \ Aggregate.3pm \ Aggregator.3pm \ Average.3pm \ ChartType.3pm \ Config.3pm \ Count.3pm \ DataTypes.3pm \ DerivedSchema.3pm \ DlfAnalyser.3pm \ DlfAnalyserProcess.3pm \ DlfCategoriser.3pm \ DlfConverter.3pm \ DlfConverterProcess.3pm \ DlfQuery.3pm \ DlfResult.3pm \ DlfSchema.3pm \ DlfStore.3pm \ DlfStream.3pm \ DocBookParser.3pm \ Error.3pm \ ExtendedSchema.3pm \ Field.3pm \ FilterExpr.3pm \ FilterSpec.3pm \ First.3pm \ Group.3pm \ GroupField.3pm \ I18N.3pm \ ImportJob.3pm \ Last.3pm \ Logger.3pm \ LrCommand.3pm \ Max.3pm \ Min.3pm \ OldDlfAdapter.3pm \ OutputFormat.3pm \ OutputJob.3pm \ Param.3pm \ Plugin.3pm \ PluginManager.3pm \ Program.3pm \ Rangegroup.3pm \ Records.3pm \ Report.3pm \ ReportConfig.3pm \ ReportJob.3pm \ ReportOperator.3pm \ ReportParser.3pm \ ReportSchedule.3pm \ ReportSection.3pm \ ReportSpec.3pm \ Sum.3pm \ Syslog.3pm \ Time.3pm \ Timegroup.3pm \ Timeslot.3pm \ UI.3pm \ Utils.3pm \ W3CExtendedLog.3pm \ WeekCalculator.3pm \ WELF.3pm \ XMLParser.3pm \ XMLSpecContainer.3pm \ XMLSpecI18N.3pm \ XMLSpecParser.3pm perlpackage = Lire transform = s,^,$(perlpackage)::, EXTRA_DIST = $(pm_s) CLEANFILES = $(man_MANS) ���������������������������������������lire-2.1.1/all/lib/Lire/Makefile.in�����������������������������������������������������������������0000644�0001750�0001750�00000065335�11677606132�013672� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/include/rules.mk subdir = all/lib/Lire ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(allperllib_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" transform = s,^,$(perlpackage)::, ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done SUBDIRS = ChartTypes OutputFormats Report ReportParser SQLExt Test Config UI allperllibdir = $(LR_PERL5LIBDIR)/Lire pm_s = \ Aggregate.pm \ Aggregator.pm \ Average.pm \ ChartType.pm \ Config.pm \ Count.pm \ DataTypes.pm \ DerivedSchema.pm \ DlfAnalyser.pm \ DlfAnalyserProcess.pm \ DlfCategoriser.pm \ DlfConverter.pm \ DlfConverterProcess.pm \ DlfQuery.pm \ DlfResult.pm \ DlfSchema.pm \ DlfStore.pm \ DlfStream.pm \ DocBookParser.pm \ Error.pm \ ExtendedSchema.pm \ Field.pm \ FilterExpr.pm \ FilterSpec.pm \ First.pm \ Group.pm \ GroupField.pm \ I18N.pm \ ImportJob.pm \ Last.pm \ Logger.pm \ LrCommand.pm \ Max.pm \ Min.pm \ OldDlfAdapter.pm \ OutputFormat.pm \ OutputJob.pm \ Param.pm \ Plugin.pm \ PluginManager.pm \ Program.pm \ Rangegroup.pm \ Records.pm \ Report.pm \ ReportConfig.pm \ ReportJob.pm \ ReportOperator.pm \ ReportParser.pm \ ReportSchedule.pm \ ReportSection.pm \ ReportSpec.pm \ SimpleStat.pm \ Sum.pm \ Syslog.pm \ Time.pm \ Timegroup.pm \ Timeslot.pm \ UI.pm \ Utils.pm \ W3CExtendedLog.pm \ WeekCalculator.pm \ WELF.pm \ XMLParser.pm \ XMLSpecContainer.pm \ XMLSpecI18N.pm \ XMLSpecParser.pm allperllib_DATA = $(pm_s) man_MANS = \ Aggregate.3pm \ Aggregator.3pm \ Average.3pm \ ChartType.3pm \ Config.3pm \ Count.3pm \ DataTypes.3pm \ DerivedSchema.3pm \ DlfAnalyser.3pm \ DlfAnalyserProcess.3pm \ DlfCategoriser.3pm \ DlfConverter.3pm \ DlfConverterProcess.3pm \ DlfQuery.3pm \ DlfResult.3pm \ DlfSchema.3pm \ DlfStore.3pm \ DlfStream.3pm \ DocBookParser.3pm \ Error.3pm \ ExtendedSchema.3pm \ Field.3pm \ FilterExpr.3pm \ FilterSpec.3pm \ First.3pm \ Group.3pm \ GroupField.3pm \ I18N.3pm \ ImportJob.3pm \ Last.3pm \ Logger.3pm \ LrCommand.3pm \ Max.3pm \ Min.3pm \ OldDlfAdapter.3pm \ OutputFormat.3pm \ OutputJob.3pm \ Param.3pm \ Plugin.3pm \ PluginManager.3pm \ Program.3pm \ Rangegroup.3pm \ Records.3pm \ Report.3pm \ ReportConfig.3pm \ ReportJob.3pm \ ReportOperator.3pm \ ReportParser.3pm \ ReportSchedule.3pm \ ReportSection.3pm \ ReportSpec.3pm \ Sum.3pm \ Syslog.3pm \ Time.3pm \ Timegroup.3pm \ Timeslot.3pm \ UI.3pm \ Utils.3pm \ W3CExtendedLog.3pm \ WeekCalculator.3pm \ WELF.3pm \ XMLParser.3pm \ XMLSpecContainer.3pm \ XMLSpecI18N.3pm \ XMLSpecParser.3pm perlpackage = Lire EXTRA_DIST = $(pm_s) CLEANFILES = $(man_MANS) all: all-recursive .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/Lire/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/Lire/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man3: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list=''; test -n "$(man3dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } install-allperllibDATA: $(allperllib_DATA) @$(NORMAL_INSTALL) test -z "$(allperllibdir)" || $(MKDIR_P) "$(DESTDIR)$(allperllibdir)" @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(allperllibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(allperllibdir)" || exit $$?; \ done uninstall-allperllibDATA: @$(NORMAL_UNINSTALL) @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(allperllibdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(allperllibdir)" && rm -f $$files # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-recursive all-am: Makefile $(MANS) $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-allperllibDATA install-man install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man3 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-allperllibDATA uninstall-man uninstall-man: uninstall-man3 .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \ ctags-recursive install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am check-local clean clean-generic \ ctags ctags-recursive distclean distclean-generic \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-allperllibDATA install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man3 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-allperllibDATA uninstall-am uninstall-man \ uninstall-man3 .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ReportOperator.pm�����������������������������������������������������������0000644�0001750�0001750�00000022417�10460673255�015143� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ReportOperator; use strict; use base qw/ Exporter /; use Lire::I18N qw/ dgettext /; use Lire::Utils qw/ check_param check_object_param /; use Carp; our @EXPORT_OK = qw/ group_data_value /; =pod =head1 NAME Lire::ReportOperator - Base class for all operators that can be used to compute reports =head1 SYNOPSIS print $op->name(), "\n"; print $op->op(), "\n"; print $op->label(), "\n"; =head1 DESCRIPTION The Lire::ReportOperator is the base class for all operators that can be used to compute the data appearing in Lire's reports. This class only provides the behavior common to all operators. Currently, the operators defined in Lire come into two main varieties: first, there are aggregators which are operators that can split DLF records into multiple groups, second there are group operators that can compute data based on a group of DLF records. Aggregators are subclasses of Lire::Aggregator and group operations are subclasses of Lire::Aggregate. =head1 METHODS =head2 op() Returns the XML element's name which refers to this operator. =cut sub op { return $_[0]{'op'}; } =pod =head2 report_spec() Returns the Lire::ReportSpec object in which this operator is. =cut sub report_spec { return $_[0]{'report_spec'}; } =pod =head2 parent() Returns the parent of this operator. This will be undefined for the top-level aggregator in the report specification. Only Lire::Aggregator can have children and as such be a parent. =cut sub parent { return $_[0]{'parent'}; } =pod =head2 last_parent() Returns our top-level parent. =cut sub last_parent { my ( $self ) = @_; my $parent = $self; while ( $parent->parent() ) { $parent = $parent->parent() } return $parent; } =pod =head2 name( [$new_name] ) Returns the name of this operator in the current report specification. The operator's name is an identifier that must be unique in a given report specification. This name will be used to identify the values generated by this operator in the generated report. If $new_name is set, this operator's name will be changed to this new value. =cut sub name { croak "Unimplemented name() method in ", ref $_[0]; } =pod =head2 has_label() Returns true if this operator has an explicit label assigned. =cut sub has_label { return defined $_[0]->{'label'}; } =pod =head2 label( [$new_label] ) Returns what should be used as column's label for the data generated by this operator. If the second argument is set, the column label will be set to this new value. =cut sub label { my ( $self, $label ) = @_; $self->{'label'} = $label if @_ == 2; return dgettext( 'lire-' . $self->{'report_spec'}->superservice(), ( $self->{'label'} ? $self->{'label'} : $self->name() ) ); } =pod =head1 METHODS FOR SUBCLASSES Subclasses must use a hash to represent their instance data. They should call init() from their constructor method. =head2 init( %params ) Lire::Report is an abstract class which shouldn't be instanciated directly. Subclasses should call the init() method in their constructor. This method initializes the attributes common to all operators. The %params keys that should be defined are: =over =item op The operator's kind. That's the XML element's name. It's a mandatory parameter. =item parent This operator's parent. This must be present unless the element is the top-level aggregator. =item report_spec The report specification in which this operator is added. =item label This operator's label. This is an optional information. =back This method returns the object. =cut sub init { my ( $self, %args ) = @_; check_param( $args{'op'}, 'op' ); check_object_param( $args{'report_spec'}, 'report_spec', 'Lire::ReportSpec' ); check_object_param( $args{'parent'}, 'parent', 'Lire::Aggregator' ) if ( defined $args{'parent'} ); $self->{'report_spec'} = $args{'report_spec'}; $self->{'op'} = $args{'op'}; $self->{'parent'} = $args{'parent'}; $self->label( $args{'label'} ) if defined $args{'label'}; return; } =pod =head2 print( $fh, $prefix ) This is the method which is called to write an XML representation of this operator. $fh is the file handle onto which to output the XML representation. $indent is an integer which gives the number of spaces which should be used as indentation when writing the XML. =cut sub print { croak( "unimplemented print() method" ); } =pod =head2 build_query( $query ) =cut sub build_query { croak( "unimplemented build_query() method in ", ref $_[0] ); } =pod =head1 MERGING API The methods should be implemented to support merging of data generated by this operator from two reports. =cut =pod =head2 init_merge() This method is called once before merging of XML reports is started. =cut sub init_merge { croak "Unimplemented init_merge() method in ", ref $_[0], "\n"; } =pod =head2 end_merge() This method is once after all the XML reports were merged. =cut sub end_merge { croak "Unimplemented end_merge() method in ", ref $_[0], "\n"; } =pod =head2 init_group_data() This method should return a data structure that will be passed the call to update_group_data() and merge_group_data(). There will be one such data structure for every group that exists in the aggregator containing this operator. There are a few restrictions placed on this data structure in order to assure that it can be sorted by aggregator that need to sort their entries. If the data structure is =over =item SCALAR That value can be used for sorting purpose. =item SCALAR REFERENCE The scalar value will be used as sorting key. =item ARRAY REFERENCE The first item in the array reference will be used as sorting key. =item HASH REFERENCE The C<sort_value> items in the hash will be used as sorting key. =item OBJECT REFERENCE The value returned by the sort_value() method will be used as sorting key. =back A function group_data_value() can be used to extract the sorting key value according to these rules. It can be imported: use Lire::ReportOperator qw/group_data_value/; my $v = group_data_value( $data ); =cut sub init_group_data { croak "Unimplemented init_group_data() method in ", ref $_[0], "\n"; } =pod =head2 merge_group_data( $value, $data ) This method will be called once for each value generated by this operator in the XML reports to be merged. The $value parameter can be either an hash reference or a Lire::Report::Group object. It will be the same things that was generated by this operator. $data is the group data structure returned by init_group_data() for the group where this $value should be merged. =cut sub merge_group_data { croak "Unimplemented merge_group_data() method in", ref $_[0], "\n"; } =pod =head2 end_group_data( $data ) This method will be called once for every group that was created by the aggregator containing this operator. The $data parameter is the data structure that was returned by init_group_data() for the current group. One possible use of this method would be, for example, for the avg operator to compute the actual average since it cannot be done until all the records are processed. =cut sub end_group_data { croak "Unimplemented end_group_data() method in", ref $_[0], "\n"; } =pod =head2 add_entry_value( $entry, $data ) This method will be called once for each group created in by the aggregator. In this method, the operator should add the appropriate name and value for this entry. $entry is the Lire::Report::Entry object to which the names and/or values should be added. $data is the data structure returned by init_group_data() corresponding for the current group. For example, its in this method that the sum operator will add the value containing the sum for the current entry. =cut sub add_entry_value { croak "Unimplemented add_entry_value() method in ", ref $_[0], "\n"; } =pod =head2 group_data_value($data) Returns the "value" from one data item created by a init_group_data() method. This is a function not a method. =cut sub group_data_value { if ( ref $_[0] eq 'SCALAR' ) { return ${$_[0]}; } elsif (ref $_[0] eq 'ARRAY' ) { return $_[0][0]; } elsif (ref $_[0] eq 'HASH' ) { return $_[0]{'sort_value'}; } elsif (ref $_[0]) { return $_[0]->sort_value; } else { return$_[0]; } } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::Aggregate(3pm), Lire::Aggregator(3pm). =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: ReportOperator.pm,v 1.21 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Plugin.pm�������������������������������������������������������������������0000644�0001750�0001750�00000005071�10460673255�013407� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Plugin; use strict; use Carp; =pod =head1 NAME Lire::Plugin - Base interface of all Lire plugins. =head1 SYNOPSIS use base qw/ Lire::Plugin /; =head1 DESCRIPTION This package defines the base interface implemented by all plugins. =head1 DEFAULT CONSTRUCTOR The plugin class has new() constructor which blesses an hash reference. =cut sub new { return bless {}, shift; } =pod =head2 name() Returns the name of the plugin. =cut sub name { croak "name() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 title() Returns a more human friendly name for the plugin. =cut sub title { croak "title() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 description() Returns a DocBook XML based documentation of the plugin. =cut sub description { croak "description() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 type Returns the type of plugin. There are three plugin types in Lire: =over =item dlf_converter These plugins are used to converter log files to DLF. Plugin will also need to implement the Lire::DlfConverter interface. =item output_format These plugins are used to format XML reports. Plugin of this type should implement the Lire::OutputFormat interface. =item dlf_analyser These plugins are used to generate other DLF records from existing Dlf records. They should implement the Lire::Analaser interface. =item chart_type These plugins are used to generate charts. =cut sub type { croak "type() not implemented by ", ref $_[0] || $_[0]; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm), Lire::DlfConverter(3pm), Lire::OutputFormat(3pm), Lire::DlfAnalyser(3pm), Lire::DlfChartType(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Plugin.pm,v 1.5 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/��������������������������������������������������������������0000755�0001750�0001750�00000000000�11677607767�014544� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/DVI.pm��������������������������������������������������������0000644�0001750�0001750�00000003763�10460673257�015437� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::OutputFormats::DVI; use strict; use base qw/Lire::OutputFormats::LaTeX/; use Locale::TextDomain 'lire'; use Lire::Config; use Lire::Error qw/ missing_command /; =pod =head1 NAME Lire::OutputFormats::DVI - DVI output format. =head1 SYNOPSIS my $format = Lire::PluginManager->get_plugin( 'output_format', 'dvi' ); $format->format_report( $xml_file, $dvi_file, $cfg ); =head1 DESCRIPTION Format a XML report into DVI with charts. =cut sub name { return 'dvi'; } sub title { return __( 'DVI' ); } sub description { return '<para>' . __( 'DVI report with charts.' ) . '</para>'; } sub missing_requirements { my @missings = shift->SUPER::missing_requirements(); push @missings, missing_command( 'lambda', 'Omega' ) unless Lire::Config->get_var( 'lambda_path' )->is_valid(); return @missings; } sub mime_filename { return "report.dvi"; } sub content_type { return "application/x-dvi"; } sub content_type_charset { return undef; } sub content_transfer_encoding { return 'base64'; } 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::OutputFormat(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: DVI.pm,v 1.4 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������lire-2.1.1/all/lib/Lire/OutputFormats/of_latex_init�������������������������������������������������0000644�0001750�0001750�00000000263�10460672576�017221� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::OutputFormats::LaTeX; Lire::PluginManager->register_plugin( new Lire::OutputFormats::LaTeX() ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/PS.pm���������������������������������������������������������0000644�0001750�0001750�00000004007�10460673257�015327� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::OutputFormats::PS; use strict; use base qw/Lire::OutputFormats::DVI/; use Locale::TextDomain 'lire'; use Lire::Config; use Lire::Error qw/ missing_command /; =pod =head1 NAME Lire::OutputFormat::PS - PostScript output format. =head1 SYNOPSIS my $format = Lire::PluginManager->get_plugin( 'output_format', 'ps' ); $format->format_report( $xml_file, $ps_file, $cfg ); =head1 DESCRIPTION Format a XML report into PostScript with charts. =cut sub name { return 'ps'; } sub title { return __( 'PostScript' ); } sub description { return '<para>' . __( 'PostScript report with charts.' ) . '</para>'; } sub missing_requirements { my @missings = shift->SUPER::missing_requirements(); push @missings, missing_command( 'odvips', 'Omega' ) unless Lire::Config->get_var( 'odvips_path' )->is_valid(); return @missings; } sub mime_filename { return "report.ps"; } sub content_type { return "application/postscript"; } sub content_type_charset { return undef; } sub content_transfer_encoding { return undef; } 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::OutputFormat(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: PS.pm,v 1.4 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/of_xml_init���������������������������������������������������0000644�0001750�0001750�00000000257�10460672576�016707� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::OutputFormats::XML; Lire::PluginManager->register_plugin( new Lire::OutputFormats::XML() ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/PDF.pm��������������������������������������������������������0000644�0001750�0001750�00000004035�10460673257�015417� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::OutputFormats::PDF; use strict; use base qw/Lire::OutputFormats::PS/; use Locale::TextDomain 'lire'; use Lire::Config; use Lire::Error qw/ missing_command /; use Lire::Utils qw/ tempdir /; eval "use MIME::Entity"; =pod =head1 NAME Lire::OutputFormat::PDF - PDF output format. =head1 SYNOPSIS my $format = Lire::PluginManager->get_plugin( 'output_format', 'pdf' ); $format->format_report( $xml_file, $pdf_file, $cfg ); =head1 DESCRIPTION Format a XML report into PDF with charts. =cut sub name { return 'pdf'; } sub title { return __( 'PDF' ); } sub description { return '<para>' . __( 'PDF report with charts.' ) . '</para>'; } sub missing_requirements { my @missings = shift->SUPER::missing_requirements(); push @missings, missing_command( 'ps2pdf' ) unless Lire::Config->get_var( 'ps2pdf_path' )->is_valid(); return @missings; } sub mime_filename { return "report.pdf"; } sub content_type { return 'application/pdf'; } sub content_type_charset { return undef; } sub content_transfer_encoding { return "base64"; } 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::OutputFormat(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: PDF.pm,v 1.4 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/LaTeX.pm������������������������������������������������������0000644�0001750�0001750�00000006454�10460673257�015772� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::OutputFormats::LaTeX; use strict; use base qw/Lire::OutputFormat/; use Locale::TextDomain 'lire'; use Lire::Config; use Lire::ReportParser::LaTeXWriter; use Lire::ReportParser::ReportBuilder; use Lire::Utils qw/tempdir/; eval "use MIME::Entity"; =pod =head1 NAME Lire::OutputFormat::LaTeX - LaTeX output format. =head1 SYNOPSIS my $format = Lire::PluginManager->get_plugin( 'output_format', 'latex' ); $format->format_report( $xml_file, $latex_file, $cfg ); =head1 DESCRIPTION Format a XML report into LaTeX with charts. =cut sub name { return 'latex'; } sub title { return __( 'LaTeX' ); } sub description { return '<para>' . __( 'LaTeX report with charts.' ) . '</para>'; } sub format_report { my ( $self, $report_file, $output_file, $cfg ) = @_; my $parser = new Lire::ReportParser::ReportBuilder(); my $report = $parser->parsefile( $report_file ); my $writer = new Lire::ReportParser::LaTeXWriter(); $writer->write_report( $report, $output_file, $self->name(), Lire::Config->get( 'lr_latex_include' ) ); return; } sub mime_filename { return "report.tex"; } sub mime_report { my ( $self, $report_file, $cfg ) = @_; my $tmpdir = tempdir( __PACKAGE__ . '_XXXXXX', 'CLEANUP' => 1 ); my $report = $tmpdir . "/" . $self->mime_filename(); $self->format_report( $report_file, $report, $cfg ); opendir my $dh, $tmpdir or die "opendir '$tmpdir' failed: $!"; my @charts = grep { /\.eps$/ } readdir $dh; closedir $dh; my $entity = MIME::Entity->build( 'Type' => $self->content_type(), 'Charset' => $self->content_type_charset(), 'Encoding' => $self->content_transfer_encoding(), 'Path' => $report ); if ( @charts ) { my $container = MIME::Entity->build( 'Type' => 'multipart/mixed' ); $container->add_part( $entity ); foreach my $chart ( @charts ) { $container->attach( 'Type' => 'application/postscript', 'Path' => "$tmpdir/$chart" ); } return $container; } return $entity; } sub content_type { return "text/x-tex"; } sub content_type_charset { return 'utf-8'; } sub content_transfer_encoding { return "quoted-printable"; } 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::OutputFormat(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: LaTeX.pm,v 1.3 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/XML.pm��������������������������������������������������������0000644�0001750�0001750�00000004073�10460673257�015450� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::OutputFormats::XML; use strict; use base qw/Lire::OutputFormat/; use Locale::TextDomain 'lire'; use File::Copy qw/copy/; eval "use MIME::Entity"; =pod =head1 NAME Lire::OutputFormats::XML - XML output format. =head1 SYNOPSIS my $format = Lire::PluginManager->get_plugin( 'output_format', 'xml' ); $format->format_report( $xml_file, $xml_file ); =head1 DESCRIPTION Lire::OutputFormat implementation which saves the report as LRML XML. =cut sub name { return 'xml'; } sub title { return __( 'XML' ); } sub description { return '<para>' . __( 'Native XML format. This keeps the report in Lire Report Markup Language.' ) . '</para>'; } sub format_report { my ( $self, $report_file, $output_file ) = @_; copy( $report_file, $output_file ); return; } sub mime_report { my ( $self, $report_file, $cfg ) = @_; return MIME::Entity->build( 'Type' => 'text/xml', 'Charset' => 'utf-8', 'Encoding' => 'quoted-printable', 'Path' => $report_file ); } 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::OutputFormat(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: XML.pm,v 1.2 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/Excel95.pm����������������������������������������������������0000644�0001750�0001750�00000004662�10460673257�016232� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::OutputFormats::Excel95; use strict; use base qw/Lire::OutputFormat/; use Locale::TextDomain 'lire'; use Lire::Utils qw/tempdir/; eval "use MIME::Entity;"; eval "use Lire::ReportParser::ExcelWriter;"; our $HAS_EXCEL95 = ! $@; =pod =head1 NAME Lire::OutputFormats::Excel95 - Excel95 output format. =head1 SYNOPSIS my $format = Lire::PluginManager->get_plugin( 'output_format', 'excel95' ); $format->format_report( $xml_file, $xls_file ); =head1 DESCRIPTION Format a XML report into Excel95 spreadsheet. =cut sub name { return 'excel95'; } sub title { return __( 'Excel95 Spreadsheet' ); } sub description { return '<para>' . __( 'Format the report as a Excel95 spreadsheet.' ) . '</para>'; } sub missing_requirements { return $HAS_EXCEL95 ? () : ( __( 'missing CPAN module Spreadsheet::WriteExcel' ) ); } sub format_report { my ( $self, $report_file, $output_file ) = @_; my $parser = Lire::ReportParser::ExcelWriter->new( 'output_file' => $output_file ); $parser->parsefile( $report_file ); return; } sub mime_report { my ( $self, $report_file, $cfg ) = @_; my $tmpdir = tempdir( __PACKAGE__ . '_XXXXXX', 'CLEANUP' => 1 ); $self->format_report( $report_file, "$tmpdir/report.xls", $cfg ); return MIME::Entity->build( 'Type' => 'application/vnd.ms-excel', 'Encoding' => 'base64', 'Path' => "$tmpdir/report.xls" ); } 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::OutputFormat(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Excel95.pm,v 1.4 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/of_dvi_init���������������������������������������������������0000644�0001750�0001750�00000000257�10460672576�016671� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::OutputFormats::DVI; Lire::PluginManager->register_plugin( new Lire::OutputFormats::DVI() ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/of_txt_init���������������������������������������������������0000644�0001750�0001750�00000000261�10460672576�016721� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::OutputFormats::Text; Lire::PluginManager->register_plugin( new Lire::OutputFormats::Text() ); �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/of_txt.xml����������������������������������������������������0000644�0001750�0001750�00000001277�10460672576�016505� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.1//EN" "http://www.logreport.org/LRCSML/1.1/lrcsml.dtd"> <lrcsml:config-spec xmlns:lrcsml="http://www.logreport.org/LRCSML/"> <lrcsml:record name="txt_properties"> <lrcsml:string name="encoding"> <lrcsml:summary>Encoding used in the formatted reports.</lrcsml:summary> <lrcsml:description> <para>Use this parameter in the case where you want your reports formatted in a different encoding than the system's default.</para> </lrcsml:description> </lrcsml:string> </lrcsml:record> </lrcsml:config-spec> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/Makefile.am���������������������������������������������������0000644�0001750�0001750�00000003424�10114501643�016466� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.3 2004/08/30 01:32:19 flacoste Exp $ ## Copyright (C) 2000-2001 Stichting LogReport Foundation LogReport@LogReport.org ## ## This file is part of Lire. ## ## Lire is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk specdir = $(datadir)/$(PACKAGE)/config-spec spec_DATA = \ of_html.xml \ of_txt.xml pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins plugins_DATA = \ of_dvi_init \ of_excel95_init \ of_html_init \ of_latex_init \ of_pdf_init \ of_ps_init \ of_txt_init \ of_xml_init allperllibdir = $(LR_PERL5LIBDIR)/Lire/OutputFormats pm_s = \ DVI.pm \ Excel95.pm \ HTML.pm \ LaTeX.pm \ PDF.pm \ PS.pm \ Text.pm \ XML.pm allperllib_DATA = $(pm_s) man_MANS = \ DVI.3pm \ Excel95.3pm \ HTML.3pm \ LaTeX.3pm \ PDF.3pm \ PS.3pm \ Text.3pm \ XML.3pm perlpackage = Lire::OutputFormats transform = s,^,$(perlpackage)::, EXTRA_DIST = $(pm_s) $(spec_DATA) $(plugins_DATA) CLEANFILES = $(man_MANS) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/Makefile.in���������������������������������������������������0000644�0001750�0001750�00000047373�11677606132�016530� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/include/rules.mk subdir = all/lib/Lire/OutputFormats ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" \ "$(DESTDIR)$(pluginsdir)" "$(DESTDIR)$(specdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(allperllib_DATA) $(plugins_DATA) $(spec_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) transform = s,^,$(perlpackage)::, ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done specdir = $(datadir)/$(PACKAGE)/config-spec spec_DATA = \ of_html.xml \ of_txt.xml plugins_DATA = \ of_dvi_init \ of_excel95_init \ of_html_init \ of_latex_init \ of_pdf_init \ of_ps_init \ of_txt_init \ of_xml_init allperllibdir = $(LR_PERL5LIBDIR)/Lire/OutputFormats pm_s = \ DVI.pm \ Excel95.pm \ HTML.pm \ LaTeX.pm \ PDF.pm \ PS.pm \ Text.pm \ XML.pm allperllib_DATA = $(pm_s) man_MANS = \ DVI.3pm \ Excel95.3pm \ HTML.3pm \ LaTeX.3pm \ PDF.3pm \ PS.3pm \ Text.3pm \ XML.3pm perlpackage = Lire::OutputFormats EXTRA_DIST = $(pm_s) $(spec_DATA) $(plugins_DATA) CLEANFILES = $(man_MANS) all: all-am .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/Lire/OutputFormats/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/Lire/OutputFormats/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man3: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list=''; test -n "$(man3dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } install-allperllibDATA: $(allperllib_DATA) @$(NORMAL_INSTALL) test -z "$(allperllibdir)" || $(MKDIR_P) "$(DESTDIR)$(allperllibdir)" @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(allperllibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(allperllibdir)" || exit $$?; \ done uninstall-allperllibDATA: @$(NORMAL_UNINSTALL) @list='$(allperllib_DATA)'; test -n "$(allperllibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(allperllibdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(allperllibdir)" && rm -f $$files install-pluginsDATA: $(plugins_DATA) @$(NORMAL_INSTALL) test -z "$(pluginsdir)" || $(MKDIR_P) "$(DESTDIR)$(pluginsdir)" @list='$(plugins_DATA)'; test -n "$(pluginsdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pluginsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pluginsdir)" || exit $$?; \ done uninstall-pluginsDATA: @$(NORMAL_UNINSTALL) @list='$(plugins_DATA)'; test -n "$(pluginsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(pluginsdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(pluginsdir)" && rm -f $$files install-specDATA: $(spec_DATA) @$(NORMAL_INSTALL) test -z "$(specdir)" || $(MKDIR_P) "$(DESTDIR)$(specdir)" @list='$(spec_DATA)'; test -n "$(specdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(specdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(specdir)" || exit $$?; \ done uninstall-specDATA: @$(NORMAL_UNINSTALL) @list='$(spec_DATA)'; test -n "$(specdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(specdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(specdir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(allperllibdir)" "$(DESTDIR)$(pluginsdir)" "$(DESTDIR)$(specdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-allperllibDATA install-man \ install-pluginsDATA install-specDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man3 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-allperllibDATA uninstall-man \ uninstall-pluginsDATA uninstall-specDATA uninstall-man: uninstall-man3 .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ distclean distclean-generic distdir dvi dvi-am html html-am \ info info-am install install-allperllibDATA install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-man3 \ install-pdf install-pdf-am install-pluginsDATA install-ps \ install-ps-am install-specDATA install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am uninstall uninstall-allperllibDATA \ uninstall-am uninstall-man uninstall-man3 \ uninstall-pluginsDATA uninstall-specDATA .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/of_html.xml���������������������������������������������������0000644�0001750�0001750�00000002571�10460672576�016630� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.1//EN" "http://www.logreport.org/LRCSML/1.1/lrcsml.dtd"> <lrcsml:config-spec xmlns:lrcsml="http://www.logreport.org/LRCSML/" xmlns:lrcml="http://www.logreport.org/LRCML/"> <lrcsml:record name="html_properties"> <lrcsml:boolean name="charts" summary="Obsolete" obsolete="1" /> <lrcsml:boolean name="one_page"> <lrcsml:summary>Generate the report on one page</lrcsml:summary> <lrcsml:description> <para>If you want your report to be diplayed on one page, enable this option. Otherwise a multiple page document will be generated.</para> </lrcsml:description> <lrcml:param name="one_page" value="0" /> </lrcsml:boolean> <lrcsml:boolean name="xhtml"> <lrcsml:summary>Use XHTML 1.0 syntax</lrcsml:summary> <lrcsml:description> <para>XHTML is the modern form of HTML. XHTML files are actually XML files with an HTML vocabulary. Since XHTML 1.0 is just a little bit more than HTML 4.01, the result displayed will not change considerably but certain people like to live on the bleeding edge...</para> </lrcsml:description> <lrcml:param name="xhtml" value="1" /> </lrcsml:boolean> </lrcsml:record> </lrcsml:config-spec> ���������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/HTML.pm�������������������������������������������������������0000644�0001750�0001750�00000007164�10460673257�015560� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::OutputFormats::HTML; use strict; use base qw/Lire::OutputFormat/; use Locale::TextDomain 'lire'; use Lire::ReportParser::HTMLWriter; use Lire::ReportParser::ReportBuilder; use Lire::Utils qw/tempdir file_content/; eval "use MIME::Entity"; =pod =head1 NAME Lire::OutputFormats::HTML - HTML output format. =head1 SYNOPSIS my $format = Lire::PluginManager->get_plugin( 'output_format', 'html' ); $format->format_report( $xml_file, $htmldir, $cfg ); =head1 DESCRIPTION Format a XML report into HTML or XHTML with charts. =cut sub name { return 'html'; } sub title { return __( '(X)HTML' ); } sub description { return '<para>' . __( 'HTML Report with charts, if ploticus is available.' ) . '</para>'; } sub format_report { my ( $self, $report_file, $output_file, $cfg ) = @_; my $parser = new Lire::ReportParser::ReportBuilder(); my $report = $parser->parsefile( $report_file ); my $writer = new Lire::ReportParser::HTMLWriter(); $writer->write_report( $report, $output_file, %$cfg ); return; } my %types = ( 'png' => 'image/png', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'gif' => 'image/gif', 'css' => 'text/css', ); sub mime_report { my ( $self, $report_file, $cfg ) = @_; my $tmpdir = tempdir( __PACKAGE__ . '_XXXXXX', 'CLEANUP' => 1 ); my %args = $cfg ? %$cfg : (); $args{'one_page'} = 1; $self->format_report( $report_file, $tmpdir, \%args ); my $entity = MIME::Entity->build( 'Type' => 'multipart/related' ); $entity->attach( 'Type' => 'text/html', 'Charset' => 'utf-8', 'Encoding' => 'quoted-printable', 'Data' => setcid( "$tmpdir/index.html" ) ); opendir my $dh, $tmpdir or die "opendir '$tmpdir' failed: $!"; foreach my $file ( sort readdir $dh ) { next if $file =~ /^(\.|\.\.|index\.html)$/; my ($ext) = $file =~ /\.(\w+$)/; my $type = $types{lc $ext} || 'application/octet-stream'; $entity->attach( Path => "$tmpdir/$file", Id => "<" . $file . ">", Type => $type, Encoding => $type =~ /^text/ ? 'quoted-printable' : 'base64' , ); } closedir $dh; return $entity; } sub relurl2cid { my ( $attr, $url ) = @_; if ( $url =~ /^([-.\w]+)(#.*)?$/ ) { $url = "cid:$1"; $url .= $2 if defined $2; } return qq{$attr="$url"}; } sub setcid { my $file = $_[0]; my $content = file_content( $file ); $content =~ s/(href|src)=['"](.*?)['"]/relurl2cid( $1, $2 )/eg; # return $content; } 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::OutputFormat(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: HTML.pm,v 1.2 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/Text.pm�������������������������������������������������������0000644�0001750�0001750�00000004763�10460673257�015742� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::OutputFormats::Text; use strict; use base qw/Lire::OutputFormat/; use Locale::TextDomain 'lire'; use Lire::ReportParser::AsciiWriter; use Lire::Utils qw/tempdir/; use Lire::Error qw/ file_not_writable /; eval "use MIME::Entity"; =pod =head1 NAME Lire::OutputFormats::Text - Text output format. =head1 SYNOPSIS my $format = Lire::PluginManager->get_plugin( 'output_format', 'text' ); $format->format_report( $xml_file, $text_file, $cfg ); =head1 DESCRIPTION Format a XML report into plain text. =cut sub name { return 'txt'; } sub title { return __( 'Plain Text' ); } sub description { return '<para>' . __( 'Plain Text format.' ) . '</para>'; } sub format_report { my ( $self, $report_file, $output_file, $cfg ) = @_; open my $fh, "> $output_file" or die file_not_writable( $output_file ), "\n"; my $parser = new Lire::ReportParser::AsciiWriter( 'output' => $fh, 'encoding' => $cfg->{'encoding'} ); $parser->parsefile( $report_file ); close $fh; return; } sub mime_report { my ( $self, $report_file, $cfg ) = @_; my $tmpdir = tempdir( __PACKAGE__ . '_XXXXXX', 'CLEANUP' => 1 ); $self->format_report( $report_file, "$tmpdir/report.txt", $cfg ); return MIME::Entity->build( 'Type' => 'text/plain', 'Charset' => $cfg->{'encoding'}, 'Encoding' => 'quoted-printable', 'Path' => "$tmpdir/report.txt" ); } 1; __END__ =pod =head1 SEE ALSO Lire::PluginManager(3pm) Lire::OutputFormat(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Text.pm,v 1.2 2006/07/23 13:16:31 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������lire-2.1.1/all/lib/Lire/OutputFormats/of_html_init��������������������������������������������������0000644�0001750�0001750�00000000261�10460672576�017046� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::OutputFormats::HTML; Lire::PluginManager->register_plugin( new Lire::OutputFormats::HTML() ); �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/of_excel95_init�����������������������������������������������0000644�0001750�0001750�00000000267�10460672576�017366� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::OutputFormats::Excel95; Lire::PluginManager->register_plugin( new Lire::OutputFormats::Excel95() ); �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/of_ps_init����������������������������������������������������0000644�0001750�0001750�00000000255�10460672576�016527� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::OutputFormats::PS; Lire::PluginManager->register_plugin( new Lire::OutputFormats::PS() ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/OutputFormats/of_pdf_init���������������������������������������������������0000644�0001750�0001750�00000000257�10460672576�016660� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Register the Plugin with the Lire framework. use Lire::PluginManager; use Lire::OutputFormats::PDF; Lire::PluginManager->register_plugin( new Lire::OutputFormats::PDF() ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/DlfResult.pm����������������������������������������������������������������0000644�0001750�0001750�00000007461�10460673254�014061� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::DlfResult; use strict; use Carp; use Lire::I18N qw/ mark_unicode /; use Lire::Utils qw/ check_param /; =pod =head1 NAME Lire::DlfResult - interface with the database handler for returned data =head1 SYNOPSIS use Lire::DlfResult; =head1 DESCRIPTION =head2 new( $query, $sql ) This is the constructor method for the Lire::DlfResult class. It takes a Lire::DlfQuery object and an SQL statement string as parameters. This method should never be called directly. Lire::DlfQuery will return appropriate instances of Lire::DlfResult through its execute() and execute_summary() methods. =cut sub new { my ( $class, $query, $sql, $store ) = @_; check_param( $query, 'query' ); check_param( $sql, 'sql' ); check_param( $store, 'store' ); my $self = bless { '_query' => $query, }, $class; my $dbh = $store->_dbh(); $self->{'_sth'} = $dbh->prepare_cached( $sql ); $self->{'_sth'}->execute ( @{$query->sql_params()} ); $self->{'_finished'} = 0; return $self; } =pod =head2 dlf_query() Returns the DlfQuery object from which this DlfResult was obtained. =cut sub dlf_query { return $_[0]{'_query'}; } =pod =head2 next_row() Returns the "next row" of an executed query, that is, the first record down the last one incrementally. Returns an undefined value if called after all the records where returned and dies on subsequent calls. The record is returned as a HASH reference. =cut sub next_row { my $self = $_[0]; croak "next_row() called after undef was returned by previous call" if ($self->{'_finished'}); my $row = $self->{'_sth'}->fetchrow_arrayref(); unless ( defined $row ) { $self->{'_finished'} = 1; $self->{'_sth'}->finish(); return undef; } unless ( defined $self->{'_field_names'} ) { $self->{'_field_names'} = []; foreach my $name (@{$self->{'_sth'}{'NAME'}}) { $name = substr( $name, 1, -1) if (substr( $name, 0, 1 ) eq '"'); push @{$self->{'_field_names'}}, $name; } } my $new = {}; my $i = 0; foreach my $field ( @{$self->{'_field_names'}} ) { $new->{$field} = mark_unicode( $row->[$i++] ); } return $new; } =pod =head2 next_row_aref() Same as next_row() except that the record is returned as an ARRAY reference. =cut sub next_row_aref { my $self = $_[0]; croak "next_row_aref() called after undef was returned by previous call" if ($self->{'_finished'}); my $row = $self->{'_sth'}->fetchrow_arrayref(); unless ( defined $row ) { $self->{'_finished'} = 1; $self->{'_sth'}->finish(); return undef; } return [ map { mark_unicode( $_ ) } @$row ]; } sub DESTROY { my $self = $_[0]; unless ( $self->{'_finished'}) { $self->{'_sth'}->finish(); } } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfQuery(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <wolfgang@logreport.org> =head1 VERSION $Id: DlfResult.pm,v 1.12 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Timeslot.pm�����������������������������������������������������������������0000644�0001750�0001750�00000031526�10460673256�013756� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Timeslot; use strict; use base qw/ Lire::Aggregator /; use Carp; use POSIX qw/ setlocale strftime LC_TIME /; use Lire::Aggregator; use Lire::DataTypes qw/ check_duration duration2sec minutely_duration hourly_duration daily_duration weekly_duration monthly_duration /; use Lire::Utils qw/ sql_quote_name /; use Lire::WeekCalculator; use vars qw/ @MONTHS @DAYS %unit_index /; BEGIN { @MONTHS = qw/January February March April May June July August September October November December/; @DAYS = qw/Sunday Monday Tuesday Wednesday Thursday Friday Saturday/; %unit_index = ( 'h' => 2, 'd' => 6, 'M' => 4, 'm' => 1, 's' => 0 ); } =pod =head1 NAME Lire::Timegroup - Base class for implementation of the timeslot aggregator =head1 SYNOPSIS use Lire::Timeslot; =head1 DESCRIPTION This module is the base class for implementation of the timeslot aggregator. This aggregator will split the DLF records based on a unit of time. For example, if the unit is 1h, all DLF records occuring on the same hour of day (independant of the day on which it occurs) are grouped together. =head1 CONSTRUCTOR =head2 new( %params ) Creates a new instance of a timegroup aggregator. In addition to the normal report operator parameters, the timegroup aggregator can take several parameters: =over =item field This optional parameter contains the DLF field which contains the time value used to group the DLF records together. See the field() method for more information. =item unit This mandatory parameter should contains the time unit that will be used to group the records. See the unit() method for more information. =back =cut sub new { my $proto = shift; my $class = ref( $proto) || $proto; my %params = @_; croak( "Missing unit parameter" ) unless exists $params{'unit'}; my $self = bless {}, $class; $self->SUPER::init( %params, 'op' => "timeslot" ); $self->field( $params{'field'} ); $self->unit( $params{'unit'} ); return $self; } =pod =head1 METHODS =head2 field( [$new_field] ) Returns the DLF field's name that is used to group the DLF records. This should be a valid timestamp DLF field in the current schema. By default, the default timestamp field of the DLF schema is used. You can change the field by passing a $new_field parameter. =cut sub field { my ( $self, $field ) = @_; if (@_ == 2 ) { if ( defined $field ) { croak "'$field' isn't a valid field for the specification's schemas" unless $self->report_spec()->has_field( $field ); croak "'$field' isn't a timestamp field" unless $self->report_spec()->field( $field )->type() eq "timestamp"; } else { $field = $self->report_spec()->schema()->timestamp_field()->name(); } $self->{'field'} = $field; } return $self->{'field'}; } =pod =head2 unit( [$new_unit]) Returns the time unit that will be used to group the DLF records. The unit is expressed as a duration value (for example 1s), but it should be noted that this will group the records based on the second unit of the DLF record's timestamp value. It could also be the name of a report specification's parameter containing a duration value. The time unit can be changed by using the $new_unit parameter. =cut sub unit { my ( $self, $unit ) = @_; if (@_ == 2 ) { my $unit_sec; if ( $unit =~ /^\$/ ) { my $name = substr $unit, 1; croak "$name isn't a defined parameter" unless $self->report_spec->has_param( $name ); croak "$name parameter isn't of type duration" unless $self->report_spec->param( $name )->type() eq "duration"; } else { croak "$unit isn't a valid duration" unless check_duration( $unit ); } $self->{'unit'} = $unit; } return $self->{'unit'}; } # ------------------------------------------------------------------------ # Method xml_attrs() # # Implementation of the method required by Lire::Aggregator sub xml_attrs { my ( $self ) = @_; return qq{field="$self->{'field'}" unit="$self->{'unit'}"}; } # Implements Lire::ReportOperator::name() sub name { return 'timeslot:' . $_[0]->{'field'}; } # ------------------------------------------------------------------------ # Method create_categorical_info( $info ) # # Implementation of the method required by Lire::Aggregator sub create_categorical_info { my ( $self, $info ) = @_; my $dlf_field = $self->report_spec()->field( $self->field() ); $info->create_column_info( $self->name(), 'categorical', $dlf_field->type(), $self->label() ); } sub build_query { my ( $self, $query ) = @_; $self->SUPER::build_query( $query ); my $unit = $self->report_spec()->resolve_param_ref( $self->{'unit'} ); my ( $range, $unit_char ) = $unit =~ /(\d+)\s*(\w)/; my $func = ( $unit_char eq 'w' ) ? 'lr_timeslot_week' : 'lr_timeslot'; my $param = ",$range"; $param .= ",'$unit_char'" if ( $unit_char ne 'w' ); $query->add_group_field( $self->name(), sprintf( '%s(%s%s)', $func, sql_quote_name( $self->{'field'} ), $param) ); $query->set_sort_spec( $self->name() ); return; } sub create_entry { my ( $self, $group, $row ) = @_; my $entry = $group->create_entry(); my $slot = $row->{ $self->name() }; unless ( defined $slot ) { $group->missing_cases( $row->{'_lr_nrecords'} ); return undef; } my $unit = $self->report_spec->resolve_param_ref($self->{'unit'}); my ( $range, $unit_char ) = $unit =~ /(\d+)\s*(\w)/; my $idx = int( $slot / $range ); my ($content, $value); if ( $unit_char eq 'M' ) { $value = "M$idx"; $content = $MONTHS[$slot]; } elsif ( $unit_char eq 'd' ) { $value = "D$idx"; $content = $DAYS[$slot]; } elsif ( $unit_char eq 'w' ) { $value = "W". int ( ( ($slot || 1) -1) / $range ); my $fmt = Lire::Config->get( 'lr_week_numbering' ) eq 'ISO' ? '-W%02d' : 'Week %02d'; $content = sprintf( $fmt, $slot ); } else { $value = $unit_index{$unit_char} .'-' . $idx; my %unit_fmts = ( 'h' => '%.2d:00', 'm' => '00:%.2d', 's' => '00:00:%.2d' ); $content = sprintf( $unit_fmts{$unit_char}, $slot ); } $entry->add_name( $content, $value, $range ); return $entry; } use vars qw/ @SLOT_UNIT @MAX_SLOTS @SLOT_INDEX @SLOT_FMT /; BEGIN { # SLOT_INDEX: where in a localtime(3) struct we can find relevant entry; # since there is no weeknumber represented in localtime, we use a `wk' # as placeholder # # mday, wk, wday, hour, min, sec @SLOT_UNIT = qw/1M 1w 1d 1h 1m 1s/; @MAX_SLOTS = qw/12 52 7 24 60 60/; @SLOT_INDEX = qw/4 wk 6 2 1 0/; @SLOT_FMT = qw/mo wk dw %H:00 00:%M 00:00:%S/; } # Implements Lire::ReportOperator::init_merge() sub init_merge { my $self = $_[0]; $self->SUPER::init_merge(); my $unit = $self->report_spec()->resolve_param_ref( $self->unit() ); my $unit_sec = duration2sec( $unit ); # Determine if we have a valid duration value for a timeslot my $unit_idx = 5; if ( monthly_duration( $unit ) ) { $unit_idx = 0; } elsif ( weekly_duration( $unit ) ) { $unit_idx = 1; } elsif ( daily_duration( $unit ) ) { $unit_idx = 2; } elsif ( hourly_duration( $unit ) ) { $unit_idx = 3; } elsif ( minutely_duration( $unit ) ) { $unit_idx = 4 } else { $unit_idx = 5 } my $unit_ok = 0; my $sec = duration2sec( $SLOT_UNIT[$unit_idx] ); if ( $unit_sec >= $sec && !( $unit_sec % $sec ) ) { croak "$unit is a too big muliple of $SLOT_UNIT[$unit_idx]. ", "Max is $MAX_SLOTS[$unit_idx]" if $unit_sec > $MAX_SLOTS[$unit_idx] * $sec; $self->{'slot_index'} = $SLOT_INDEX[$unit_idx]; $self->{'time_fmt'} = $SLOT_FMT[$unit_idx]; $self->{'multiplier'} = $unit_sec / $sec; $unit_ok = 1; } croak "invalid timeslot value: must be an even multiple of 1M, 1wk, 1d, 1h, 1m or 1s" unless $unit_ok; return; } # Implements Lire::Aggregator::init_aggregator_data() sub init_aggregator_data { return []; } # Implements Lire::Aggregator::merge_aggregator_data() sub merge_aggregator_data { my ( $self, $group, $timeslots ) = @_; foreach my $e ( $group->entries() ) { my @names = $e->names(); die "wrong number of names for a timeslot subreport: ", scalar @names, "\n" unless @names == 1; my $slot = $names[0]{'value'}; my $mult = $names[0]{'range'}; # Are the multipliers compatible? # They are only if the target multiplier is a multiple # of the source one. # Non-multiple would need interpolation, which would be hard # to achieve for other operation than sum and count die "incompatible unit multiplier: $self->{'multiplier'} isn't a multiple of $mult\n" unless $self->{'multiplier'} % $mult == 0; # Are the used slot compatible? my $index; if ( $self->{'time_fmt'} eq 'mo' ) { croak "incompatible timeslot unit: $slot\n" unless $slot =~ /^M(\d+)$/; $index = $1; } elsif ( $self->{'time_fmt'} eq 'dw' ) { croak "incompatible timeslot unit: $slot\n" unless $slot =~ /^D(\d+)$/; $index = $1; } elsif ( $self->{'time_fmt'} eq 'wk' ) { croak "incompatible timeslot unit: $slot\n" unless $slot =~ /^W(\d+)$/; $index = $1; } else { my $type; ( $type, $index ) = $slot =~ /^(\d)-(\d+)$/ or croak "invalid timeslot's value attribute: $slot\n"; croak "incompatible timeslot unit: $slot\n" if $type != $self->{'slot_index'}; } # Map index when target multiplier is greater than the original one. # For example: original = 2h, target = 4h # Original: 0 2 4 6 8 10 12 14 16 18 20 22 -> 12 indices # Target: 0 4 8 12 16 20 -> 6 indices my $idx = int( $index * $mult / $self->{'multiplier'} ); my $data = $timeslots->[$idx]; unless ( defined $data ) { $data = []; my $i = 0; foreach my $op ( @{$self->ops()} ) { $data->[$i++] = $op->init_group_data(); } $timeslots->[$idx] = $data; } my $i = 0; foreach my $op ( @{$self->ops()} ) { my $value = $e->data_by_name( $op->name ); my $op_data = $data->[$i++]; $op->merge_group_data( $value, $op_data ) if ( $value ); } } return $self; } # Implements Lire::Aggregator::end_aggregator_data() sub end_aggregator_data { my ( $self, $timeslots ) = @_; # Finalize each timeslice # Either create empty one or call end_group_data on them my $last_idx; if ( $self->{'slot_index'} eq 'wk' ) { $last_idx = 52; } else { $last_idx = ( 59, 59, 23, 0, 11, 0, 6 )[$self->{'slot_index'}]; } $last_idx = int( $last_idx / $self->{'multiplier'} ); my $i = 0; while ( $i <= $last_idx ) { if ( $timeslots->[$i]) { my $data = $timeslots->[$i]; my $j = 0; foreach my $op ( @{$self->ops()} ) { $op->end_group_data( $data->[$j++] ); } } else { # Create empty set my $data =[]; my $j = 0; foreach my $op ( @{$self->ops()} ) { $data->[$j] = $op->init_group_data(); $op->end_group_data( $data->[$j++] ); } $timeslots->[$i] = $data; } $i++; } return $self; } # Implements Lire::Aggregator::create_group_entries() sub create_group_entries { my ( $self, $group, $timeslots ) = @_; for ( my $i=0; $i < @$timeslots; $i++ ) { my $row = { $self->name() => $i * $self->{'multiplier'} }; my $entry = $self->create_entry( $group, $row ); my $j = 0; foreach my $op ( @{$self->ops()} ) { $op->add_entry_value( $entry, $timeslots->[$i][$j++] ); } } return; } # keep perl happy 1; __END__ =head1 SEE ALSO Lire::ReportSpec(3pm), Lire::Group(3pm), Lire::ReportOperator(3pm), Lire::Timegroup(3pm) =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <Wolfgang.Sourdeau@Contre.COM> =head1 VERSION $Id: Timeslot.pm,v 1.27 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/XMLSpecParser.pm������������������������������������������������������������0000644�0001750�0001750�00000037334�10460673256�014611� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::XMLSpecParser; use strict; use base qw/Lire::DocBookParser Lire::Config::Parser/; use Lire::ReportSpec; use Lire::FilterSpec; use Lire::FilterExpr; use Lire::Average; use Lire::First; use Lire::Last; use Lire::Min; use Lire::Max; use Lire::Sum; use Lire::Count; use Lire::Group; use Lire::GroupField; use Lire::Rangegroup; use Lire::Records; use Lire::Timegroup; use Lire::Timeslot; use Lire::Param; use Lire::Config::ListSpec; use Lire::Config::ChartSpec; =pod =head1 NAME Lire::XMLSpecParser - Creates Lire::XMLSpecContainer object form XML files. =head1 SYNOPSIS use Lire::XMLSpecParser; my $parser = new Lire::XMLSpecParser; my $spec = $parser->parsefile( 'top-files.xml' ); =head1 DESCRIPTION This is a Lire::XMLParser subclass that can be used to creates Lire::ReportSpec and Lire::FilterSpec objects from XML files. =cut my @aggregators_mix = qw/lrsml:group lrsml:rangegroup lrsml:records lrsml:timegroup lrsml:timeslot/; my @aggregates_mix = qw/lrsml:sum lrsml:avg lrsml:min lrsml:max lrsml:first lrsml:last lrsml:count/; my @scalar_filters_mix = qw/lrsml:eq lrsml:ne lrsml:gt lrsml:ge lrsml:lt lrsml:le lrsml:match lrsml:value/; my @compound_filters_mix = qw/lrsml:and lrsml:or lrsml:not/; my @meta_infos_mix = qw/lrsml:title lrsml:description lrsml:display-spec lrsml:param-spec/; my %spec = ( 'lrsml:report-spec' => { 'start' => 'spec_start', 'end' => 'spec_end', 'content' => [ @meta_infos_mix, 'lrsml:filter-spec', 'lrsml:chart-configs', 'lrsml:report-calc-spec' ], }, 'lrsml:global-filter-spec' => { 'start' => 'spec_start', 'end' => 'spec_end', 'content' => [ @meta_infos_mix, 'lrsml:filter-spec' ], }, 'lrsml:title' => { 'start' => 'collector_start', 'char' => 'collector_char', 'end' => 'title_end', 'content' => [ 'PCDATA' ], }, 'lrsml:description' => { 'start' => 'dbk_init', 'char' => 'dbk_element_char', 'end' => 'description_end', 'content' => [ 'para' ], }, 'lrsml:display-spec' => [ 'lrsml:title', 'lrsml:description' ], 'lrsml:param-spec' => [ 'lrsml:param' ], 'lrsml:param' => { 'start' => 'lrsml_param_start', 'end' => 'lrsml_param_end', 'content' => [ 'lrsml:description' ] }, 'lrsml:filter-spec' => [ @compound_filters_mix, @scalar_filters_mix ], 'lrsml:chart-configs' => [ 'lrcml:param' ], 'lrsml:report-calc-spec' => [ @aggregators_mix ], 'lrsml:group' => [ 'lrsml:field', @aggregators_mix, @aggregates_mix ], 'lrsml:field' => [], 'lrsml:not' => { 'start' => 'compound_filter_start', 'end' => 'not_end', 'content' => [ @compound_filters_mix, @scalar_filters_mix ] }, 'lrsml:avg' => [], 'lrsml:count' => [], 'lrsml:first' => [], 'lrsml:last' => [], 'lrsml:records' => [], ); foreach my $aggr ( ( @aggregates_mix ) ) { $spec{$aggr} = { 'start' => 'aggregate_start', 'content' => [] } unless exists $spec{$aggr}; } foreach my $aggr ( @aggregators_mix ) { $spec{$aggr} = { 'start' => 'aggregator_start', 'end' => 'aggregator_end', 'content' => [ @aggregators_mix, @aggregates_mix ] } unless exists $spec{$aggr}; } foreach my $filter ( @scalar_filters_mix ) { $spec{$filter} = { 'start' => 'scalar_filter_start', 'content' => [] } unless exists $spec{$filter}; } foreach my $filter ( @compound_filters_mix ) { $spec{$filter} = { 'start' => 'compound_filter_start', 'end' => 'compound_filter_end', 'content' => [ @compound_filters_mix, @scalar_filters_mix ] } unless exists $spec{$filter}; } sub namespaces { my $self = $_[0]; my $ns = { %{$self->Lire::Config::Parser::namespaces()} }; $ns->{'http://www.logreport.org/LRSML/'} = 'lrsml'; return $ns; } sub elements_spec { my $self = $_[0]; return { %{$self->Lire::Config::Parser::elements_spec()}, %{$self->Lire::DocBookParser::elements_spec()}, %spec, }; } sub parse_start { my $self = $_[0]; $self->init_stack( 'config_spec' ); $self->init_stack( 'config_value' ); return; } sub parse_end { return $_[0]{'_spec'}; } my %factories = ( 'lrsml:avg' => 'Lire::Average', 'lrsml:count', => 'Lire::Count', 'lrsml:first' => 'Lire::First', 'lrsml:last' => 'Lire::Last', 'lrsml:min' => 'Lire::Min', 'lrsml:max' => 'Lire::Max', 'lrsml:sum' => 'Lire::Sum', 'lrsml:group' => 'Lire::Group', 'lrsml:rangegroup' => 'Lire::Rangegroup', 'lrsml:timegroup' => 'Lire::Timegroup', 'lrsml:timeslot' => 'Lire::Timeslot', 'lrsml:records' => 'Lire::Records', 'lrsml:le' => 'Lire::FilterExpr::Le', 'lrsml:lt' => 'Lire::FilterExpr::Lt', 'lrsml:ge' => 'Lire::FilterExpr::Ge', 'lrsml:gt' => 'Lire::FilterExpr::Gt', 'lrsml:eq' => 'Lire::FilterExpr::Eq', 'lrsml:ne' => 'Lire::FilterExpr::Ne', 'lrsml:value' => 'Lire::FilterExpr::Value', 'lrsml:match' => 'Lire::FilterExpr::Match', 'lrsml:and' => 'Lire::FilterExpr::And', 'lrsml:or' => 'Lire::FilterExpr::Or', 'lrsml:not' => 'Lire::FilterExpr::Not', 'lrsml:report-spec' => 'Lire::ReportSpec', 'lrsml:global-filter-spec' => 'Lire::FilterSpec', 'lrsml:field' => 'Lire::GroupField', 'lrsml:param' => 'Lire::Param', ); sub spec_start { my ( $self, $name, $attr ) = @_; $self->{'_spec'} = $factories{$name}->new(); die "missing 'id' attribute\n" unless exists $attr->{'id'}; $self->{'_spec'}->id( $attr->{'id'} ); die "missing 'superservice' attribute\n" unless exists $attr->{'superservice'}; $self->{'_spec'}->superservice( $attr->{'superservice'} ); $self->{'_spec'}->schema( $attr->{'schema'}) if exists $attr->{'schema'}; $self->{'_spec'}->joined_schemas( [ split /\s+/, $attr->{'joined-schemas'} ] ) if exists $attr->{'joined-schemas'}; $self->{'_spec'}->charttype( $attr->{'charttype'} ) if exists $attr->{'charttype'}; return; } sub spec_end { my ( $self, $name ) = @_; # Check that display-spec isn't missing die "$name is missing a title element\n" unless ( defined $self->{'_spec'}->title() ); die "$name is missing a description element\n" unless ( defined $self->{'_spec'}->description() ); die "$name is missing a display title\n" unless ( defined $self->{'_spec'}->display_title() ); return; } sub chart_configs_start { my $self = $_[0]; my $spec = new Lire::Config::ListSpec( 'name' => 'chart_configs' ); $spec->add( new Lire::Config::ChartSpec( 'name' => 'chart' ) ); $self->stack_push( 'config_spec', $spec ); $self->stack_push( 'config_value', $spec->instance() ); return; } sub chart_configs_end { my $self = $_[0]; $self->stack_pop( 'config_spec' ); foreach my $cfg ( @{$self->stack_pop( 'config_value' )->as_value()}) { $self->{'_spec'}->add_chart_config( $cfg ); } return; } sub title_end { my ( $self, $name ) = @_; my $title = $self->get_collector( 'lrsml:title' ); if ( $self->within_element( 'lrsml:display-spec' ) ) { $self->{'_spec'}->display_title( $title ); } else { $self->{'_spec'}->title( $title ); } return; } sub description_end { my ( $self, $name ) = @_; if ( $self->in_element( 'lrsml:display-spec' )) { $self->{'_spec'}->display_description( $self->dbk_string() ); } elsif ( $self->in_element( 'lrsml:param' ) ) { $self->{'_curr_param'}->description( $self->dbk_string() ); } else { $self->{'_spec'}->description( $self->dbk_string() ); } return; } sub lrsml_param_start { my ( $self, $name, $attr ) = @_; die "$name missing 'name' attribute\n" unless exists $attr->{'name'}; die "$name is missing 'type' attribute\n" unless exists $attr->{'type'}; $self->{'_curr_param'} = $factories{$name}->new( 'i18n_domain' => 'lire-'.$self->{'_spec'}->superservice(), %$attr ); $self->{'_spec'}->param( $self->{'_curr_param'}->name(), $self->{'_curr_param'} ); return; } sub lrsml_param_end { my ( $self, $name ) = @_; delete $self->{'_curr_param'}; return; } sub filter_spec_start { my ( $self, $name, $attr ) = @_; $self->init_stack( 'filter-spec' ); $self->stack_push( 'filter-spec', [] ); return; } sub filter_spec_end { my ( $self, $name ) = @_; my $expr = $self->stack_pop( 'filter-spec' ); die "filter-spec can contains only one expression" if @$expr > 1; die "filter-spec must contains one expression" if @$expr == 0; $self->{'_spec'}->filter_spec( $expr->[0] ); return; } sub compound_filter_start { my ( $self, $name, $attr ) = @_; my $parent_content = $self->stack_peek( 'filter-spec' ); push @$parent_content, $factories{$name}->new( %$attr, 'container' => $self->{'_spec'} ); $self->stack_push( 'filter-spec', [] ); return; } sub compound_filter_end { my ( $self, $name ) = @_; my $expr = $self->stack_pop( 'filter-spec' ); die "$name expression must contains at leat one expression\n" unless @$expr; $self->stack_peek( 'filter-spec' )->[-1]->expr( $expr ); return; } sub not_end { my ( $self, $name ) = @_; my $expr = $self->stack_pop( 'filter-spec' ); die "$name element must contains one expression\n" unless @$expr == 1; $self->stack_peek( 'filter-spec' )->[-1]->expr( $expr->[0] ); return; } sub scalar_filter_start { my ( $self, $name, $attr ) = @_; my $content = $self->stack_peek( 'filter-spec' ); push @$content, $factories{$name}->new( %$attr, 'container' => $self->{'_spec'} ); return; } sub report_calc_spec_start { my ($self, $name, $attr ) = @_; $self->init_stack( 'calc-spec' ); $self->init_stack( 'group-sort-fields' ); $self->stack_push( 'calc-spec', [] ); return; } sub report_calc_spec_end { my ( $self, $name ) = @_; my $curr_calc = $self->stack_pop( 'calc-spec' ); die "$name must contains one aggregator (", join( ", ", @aggregators_mix ), ")\n" unless @$curr_calc == 1; $self->{'_spec'}->calc_spec( $curr_calc->[0] ); return; } sub group_start { my ($self, $name, $attr ) = @_; # Sort fields attributes can only verified after fields and # operations are specified $self->stack_push( 'group-sort-fields', $attr->{'sort'} || '' ); $self->aggregator_start( $name, $attr ); return; } sub group_end { my ( $self, $name ) = @_; my $content = $self->stack_pop( 'calc-spec' ); my @fields = grep { UNIVERSAL::isa( $_, "Lire::GroupField" ) } @$content; my @ops = grep { UNIVERSAL::isa( $_, "Lire::ReportOperator" ) } @$content; die "$name must contains at least one field\n" unless @fields; die "$name must contains at least one aggregate\n" unless @ops; die "$name must only contains field and report operators elements\n" unless @fields + @ops == @$content; my $group = $self->stack_peek( 'calc-spec' )->[-1]; $group->group_fields( \@fields ); $group->ops( \@ops ); $group->sort_fields( [ split /\s+/, $self->stack_pop( 'group-sort-fields' ) ] ); return; } sub aggregator_start { my ( $self, $name, $attr ) = @_; my $parent_content = $self->stack_pop( 'calc-spec' ); my $parent; $parent = $self->stack_peek( 'calc-spec' )->[-1] unless $self->is_stack_empty( 'calc-spec' ); push @$parent_content, $factories{$name}->new( %$attr, 'report_spec' => $self->{'_spec'}, 'parent' => $parent ); $self->stack_push( 'calc-spec', $parent_content ); $self->stack_push( 'calc-spec', [] ); return; } sub aggregator_end { my ( $self, $name ) = @_; my $content = $self->stack_pop( 'calc-spec' ); my @ops = grep { UNIVERSAL::isa( $_, "Lire::ReportOperator" ) } @$content; die "$name must contains at least one aggregate.\n" unless @ops; die "$name must only contains aggregates\n" unless @ops == @$content; $self->stack_peek( 'calc-spec' )->[-1]->ops( \@ops ); return; } sub field_start { my ( $self, $name, $attr ) = @_; my $content = $self->stack_peek( 'calc-spec' ); push @$content, $factories{$name}->new( %$attr, 'i18n_domain' => 'lire-' . $self->{'_spec'}->superservice(), 'report_spec' => $self->{'_spec'} ); return; } sub aggregate_start { my ( $self, $name, $attr ) = @_; my $parent_content = $self->stack_pop( 'calc-spec' ); my $parent = $self->stack_peek( 'calc-spec' )->[-1]; push @$parent_content, $factories{$name}->new( %$attr, 'report_spec' => $self->{'_spec'}, 'parent' => $parent, ); $self->stack_push( 'calc-spec', $parent_content ); return; } sub avg_start { my ( $self, $name, $attr ) = @_; $attr->{'by-fields'} = [ split /\s+/, $attr->{'by-fields'}] if exists $attr->{'by-fields'}; $self->aggregate_start( $name, $attr ); return; } sub first_start { my ( $self, $name, $attr ) = @_; $attr->{'sort_fields'} = [split /\s+/, $attr->{'sort'}] if exists $attr->{'sort'}; $self->aggregate_start( $name, $attr ); return; } sub last_start { my ( $self, $name, $attr ) = @_; $attr->{'sort_fields'} = [split /\s+/, $attr->{'sort'}] if exists $attr->{'sort'}; $self->aggregate_start( $name, $attr ); return; } sub count_start { my ( $self, $name, $attr ) = @_; $attr->{'fields'} = [split /\s+/, $attr->{'fields'}] if exists $attr->{'fields'}; $self->aggregate_start( $name, $attr ); return; } sub records_start { my ( $self, $name, $attr ) = @_; $attr->{'fields'} = [ split /\s+/, $attr->{'fields'} ] if exists $attr->{'fields'}; $self->aggregate_start( $name, $attr ); return; } 1; __END__ =pod =head1 SEE ALSO Lire::XMLParser(3pm, Lire::ReportSpec(3pm), Lire::FilterSpec(3pm), Lire::XMLSpecContainer(3pm). =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: XMLSpecParser.pm,v 1.5 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/DerivedSchema.pm������������������������������������������������������������0000644�0001750�0001750�00000012773�10460673254�014662� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::DerivedSchema; # vim:syntax=perl use strict; use base qw/ Lire::DlfSchema /; use Lire::DataTypes qw/ check_superservice check_xml_name /; use Lire::Utils qw/check_param check_object_param/; use Carp; =pod =head1 NAME Lire::DerivedSchema - Defines a schema for which the records are derived from another schema =head1 SYNOPSIS my $schema = Lire::DlfSchema::load_schema( 'www-user_session' ); my $fields = $schema->fields(); =head1 DESCRIPTION A Lire::DerivedSchema defines a schema for which the records are computed by an analyser using the records of a base schema. An example of a derived schema is the www-user_session schema which computes session information from the records in the www schema. =cut sub new { my ( $class, %attr ) = @_; check_param( $attr{'id'}, 'id', \&check_xml_name ); my ( $super) = $attr{'id'} =~ /^(\w+)-/ or croak "cannot find superservice in id: '$attr{'id'}'"; croak "invalid superservice in id: $super" unless check_superservice( $super ); croak "missing base-schema attribute" unless exists $attr{'base-schema'}; my $schema = Lire::DlfSchema::load_schema( $attr{'base-schema'} ); croak "superservice of base schema doesn't match one in id: ", $schema->superservice(), " != $super" if $schema->superservice() ne $super; croak "base schema cannot be an extended schema: $attr{'base-schema'}" if $schema->isa( 'Lire::ExtendedSchema' ); check_param( $attr{'timestamp'}, 'timestamp' ); my $self = $class->SUPER::new( 'timestamp' => $attr{'timestamp'}, 'superservice' => $super, ); $self->{'id'} = $attr{'id'}; $self->{'base'} = $schema; return $self; } =pod =head2 base() Returns the Lire::DlfSchema object from which this schema's records are derived. =cut sub base { return $_[0]->{'base'}; } =pod =head2 can_join_schema( $schema ) Returns true if $schema can be joined with this schema. For a DerivedSchema, this will be true only when $schema is an ExtendedSchema of this schema or this schema's base. It is also possible to join the DerivedSchema with its base. =cut sub can_join_schema { my ( $self, $schema ) = @_; check_object_param( $schema, 'schema', 'Lire::DlfSchema' ); return ( $schema eq $self->base() || ( $schema->isa( 'Lire::ExtendedSchema' ) && ( $schema->base() eq $self || $schema->base() eq $self->base() ) ) ); } sub module { my $self = $_[0]; my $module = $self->{'module'}; eval "use $module;"; croak "error loading $module module: $@\n" if $@; my $analyser = eval { no strict 'refs'; $module->new( $self ) }; croak "error creating $module instance: $@" if $@; croak "$module module isn't of type Lire::DerivedSchema::DerivedRecordsCreator" unless UNIVERSAL::isa( $self->{'module'}, "Lire::DerivedSchema::DerivedRecordsCreator", ); return $analyser; } sub create_sql_schema { my ( $self, $store ) = @_; unless ( $store->has_dlf_stream( $self->base()->id() ) ) { $self->base()->create_sql_schema( $store ); } $self->SUPER::create_sql_schema( $store ); $store->_dbh()->do( sprintf( "CREATE TABLE %s ( src_id INT, link_id INT )", $self->sql_table( "", "_links" ) ) ); $store->_dbh()->do( sprintf( "CREATE INDEX %s ON %s ( src_id )", $self->sql_table( "", "_links_src_id_idx" ), $self->sql_table( "", "_links" ) ) ); $store->_dbh()->do( sprintf( "CREATE INDEX %s ON %s ( link_id )", $self->sql_table( "", "_links_link_id_idx" ), $self->sql_table( "", "_links" ) ) ); $store->_dbh()->do( sprintf( q{CREATE TRIGGER %s AFTER DELETE ON %s BEGIN DELETE FROM %s WHERE src_id = old.dlf_id; END }, $self->sql_table( '', '_delete_trigger' ), $self->base()->sql_table(), $self->sql_table( '', '_links' ) ) ); $store->_dbh()->do( sprintf( q{CREATE TRIGGER %s AFTER DELETE ON %s BEGIN DELETE FROM %s WHERE src_id = old.dlf_id; END }, $self->sql_table( '', '_links_delete_trigger'), $self->sql_table(), $self->sql_table( '', '_links' ) ) ); return; } sub sql_link_insert_query { my $self = $_[0]; return sprintf( 'INSERT INTO %s (src_id, link_id) VALUES(?, ?)', $self->sql_table( '', '_links' ) ); } # keep perl happy 1; __END__ =pod =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: DerivedSchema.pm,v 1.19 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �����lire-2.1.1/all/lib/Lire/ExtendedSchema.pm�����������������������������������������������������������0000644�0001750�0001750�00000015653�10460673255�015041� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ExtendedSchema; # vim:syntax=perl use strict; use base qw/ Lire::DlfSchema /; use Carp; use Lire::DlfQuery; use Lire::DataTypes qw/ check_xml_name check_superservice /; use Lire::Utils qw/check_param check_object_param sql_quote_name/; =pod =head1 NAME Lire::ExtendedSchema - Adds fields to each DLF records of a base schema =head1 SYNOPSIS my $schema = Lire::DlfSchema::load_schema( 'www-robot' ); my $ext_fields = $schema->extended_fields(); =head1 DESCRIPTION A Lire::ExtendedSchema defines a DlfSchema which adds fields to each records of a base DlfSchema. The values of the extended fields are usually computed from values based on the values of the fields in the base Dlf record. These values aren't written by Lire::DlfConverters, but by Lire::DlfAnalysers (or usually a Lire::DlfCategoriser). =cut sub new { my ( $class, %attr ) = @_; check_param( $attr{'id'}, 'id', \&check_xml_name ); my ( $super) = $attr{'id'} =~ /^(\w+)-/ or croak "cannot find superservice in id: $attr{'id'}"; croak "invalid superservice in id: $super" unless check_superservice( $super ); check_param( $attr{'base-schema'}, 'base_schema' ); my $schema = Lire::DlfSchema::load_schema( $attr{'base-schema'} ); croak "superservice of base schema doesn't match one in id: ", $schema->superservice(), " != $super" if $schema->superservice() ne $super; croak "base schema cannot be an extended schema: $attr{'base-schema'}" if $schema->isa( 'Lire::ExtendedSchema' ); my $self = $class->SUPER::new( 'timestamp' => $schema->timestamp_field()->name(), 'superservice' => $super, ); $self->{'id'} = $attr{'id'}; $self->{'base'} = $schema; $self->{'fields_by_pos'} = [ $schema->fields() ]; $self->{'extended_start_idx'} = @{$self->{'fields_by_pos'}}; $self->{'fields_by_name'} = { map { $_->name() => $_ } @{$self->{'fields_by_pos'}}}; return $self; } =pod =head2 base() Returns the Lire::DlfSchema object for which this schema's records are an extension. =cut sub base { return $_[0]->{'base'}; } =pod =head2 can_join_schema( $schema ) Returns true if $schema can be joined with this schema. For an ExtendedSchema, this will be true only when $schema is an ExtendedSchema which shares the same same than this schema. =cut sub can_join_schema { my ( $self, $schema ) = @_; check_object_param( $schema, 'schema', 'Lire::DlfSchema' ); return ( $schema->isa( 'Lire::ExtendedSchema' ) && $schema ne $self && $schema->base() eq $self->base() ); } sub is_schema_compatible { my ( $self, $schema ) = @_; return $schema eq $self->{'id'} || $self->{'base'}->is_schema_compatible( $schema ); } sub extended_fields { my $self = $_[0]; my @fields = $self->fields(); my $idx = $self->{'extended_start_idx'}; return [ @fields[$idx .. $#fields] ]; } # Extended schema only store the extended fields. # Other fields are joined using dlf_id with the superservice's schema. sub _sql_fields { my $self = $_[0]; my @fields = $self->fields(); my $idx = $self->{'extended_start_idx'}; return @fields[0, # dlf_id 1, # dlf_source $idx .. $#fields ]; } # The dlf_id and dlf_source fields should be qualified with # the table name sub dlf_query { my ( $self, $sort_spec ) = @_; my $query = new Lire::DlfQuery( $self->{'id'} ); foreach my $f ( $self->fields() ) { if ( $f->name() eq 'dlf_id' || $f->name() eq 'dlf_source' ) { $query->add_field( $f->name(), $self->sql_table() . "." . $f->name() ); } else { $query->add_field( $f->name() ); } } $query->set_sort_spec( $sort_spec ) if $sort_spec; return $query; } # When using a time delimiter, we need an inner join with the # superservice's table to access the timestamp field. sub sql_clean_query { my ( $self, $with_time ) = @_; return $self->SUPER::sql_clean_query() unless $with_time; my $super = Lire::DlfSchema::load_schema( $self->superservice() ); return sprintf( 'DELETE FROM %s WHERE dlf_id IN ( SELECT e.dlf_id FROM %s b, %s e WHERE b.dlf_id = e.dlf_id AND %s < ? )', $self->sql_table(), $super->sql_table(), $self->sql_table(), sql_quote_name( "b." . $self->{'timestamp_field'} ) ); } # When using a time delimiter, we need an inner join with the # superservice's table to access the timestamp field. sub sql_clean_period_query { my $self = $_[0]; my $super = Lire::DlfSchema::load_schema( $self->superservice() ); return sprintf( 'DELETE FROM %s WHERE dlf_id IN ( SELECT e.dlf_id FROM %s b, %s e WHERE b.dlf_id = e.dlf_id AND %s >= ? AND %s < ? )', $self->sql_table(), $super->sql_table(), $self->sql_table(), sql_quote_name( "b." . $self->{'timestamp_field'} ), sql_quote_name( "b." . $self->{'timestamp_field'} ) ); } # Since the timestamp field is only stored in the base schema's # table. We do not need to create the index. sub create_sql_schema { my ($self, $store, $remove ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); unless ( $store->has_dlf_stream( $self->base()->id() ) ) { $self->base()->create_sql_schema( $store ); } $store->_dbh()->do( "DROP TABLE " . $self->sql_table() ) if $remove; $store->_dbh()->do( $self->_create_sql_table_query() ); $store->_dbh()->do( sprintf( q{CREATE TRIGGER %s AFTER DELETE ON %s BEGIN DELETE FROM %s WHERE dlf_id = old.dlf_id; END }, $self->sql_table( '', '_delete_trigger' ), $self->base()->sql_table(), $self->sql_table() ) ); return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfSchema(3pm), Lire::DerivedSchema(3pm), Lire::DlfAnalyser(3pm), Lire::DlfCategoriser(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: ExtendedSchema.pm,v 1.24 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/WELF.pm���������������������������������������������������������������������0000644�0001750�0001750�00000013340�10460673256�012705� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::WELF; use strict; use base qw/ Exporter /; use Time::Local; use vars qw/ @EXPORT_OK /; BEGIN { @EXPORT_OK = qw//; } ######################################################################## # PARSER METHODS ######################################################################## sub new { my $self = shift; my $class = ref($self) || $self; bless $self = {}, $class; return $self; } sub welf_time { my ( $time_str ) = @_; my ($year, $month, $mday, $hours, $min, $sec, $msec, $tz ) = $time_str =~ /^(\d\d\d\d)-(\d\d?)-(\d\d?)\s+ # YYYY-MM-DD (\d\d?):(\d\d?)(?::(\d\d?)(?:\.(\d+))?)?\s* # hh:mm:ss.ms (\S+)? # TZ $/x or die "invalid WELF date string: $time_str\n"; $month--; $year -= 1900; if ( defined $tz && $tz eq 'UTC' ) { return timegm( $sec || 0, $min, $hours, $mday, $month, $year ); } elsif ( defined $tz ) { # FIXME: A little hackish. This assumes that the underlying OS # understand that value # Hopefully, it shouldn't happen too much since the WELF standard # doesn't allow a timezone extension, but i've seen UTC used in the # field. (Never saw other timezone string, so this may be dead code). local $ENV{'TZ'} = $tz; return timelocal( $sec || 0, $min, $hours, $mday, $month, $year ); } else { return timelocal( $sec || 0, $min, $hours, $mday, $month, $year ); } } sub parse { my ($self, $line) = @_; $line =~ s/\r$//; # Strip trailing CR die "not a WELF record: missing id= field" unless $line =~ /\bid=/; die "not a WELF record: missing time= field" unless $line =~ /\btime=/; my %welf = (); while ( $line =~ /\b(\w+)=(?:"(.*?)"|([^" ]+))/g) { $welf{$1} = defined $2 ? $2 : $3; # Transform time string into epoch $welf{'time'} = welf_time( $2 ) if ( $1 eq "time" ); } # SonicWall extensions handling if ( defined $welf{'src'} && index( $welf{'src'}, ":" ) != -1 ) { my @src = split /:/, $welf{'src'}; if ( @src == 3 ) { ($welf{'src'}, $welf{'src_port'}, $welf{'src_if'} ) = @src; } elsif ( $src[1] =~ /^\d+$/ ) { # Second argument looks like a port number ($welf{'src'}, $welf{'src_port'} ) = @src; } else { ($welf{'src'}, $welf{'snt_if'} ) = @src; } } if ( defined $welf{'dst'} && index( $welf{'dst'}, ":" ) != -1 ) { my @dst = split /:/, $welf{'dst'}; if ( @dst == 3 ) { ($welf{'dst'}, $welf{'dst_port'}, $welf{'dst_if'} ) = @dst; } elsif ( $dst[1] =~ /^\d+$/) { # Second argument looks like a port number ($welf{'dst'}, $welf{'dst_port'} ) = @dst; } else { ($welf{'dst'}, $welf{'dst_if'} ) = @dst; } } return \%welf; } 1; __END__ =pod =head1 NAME Lire::WELF - Base implementation of a WebTrends(tm) Enhanced Log Format parser =head1 SYNOPSIS use Lire::WELF; my $parser = new Lire::WELF; my $welf_rec = $parser->parse( $line ); =head1 DESCRIPTION This module defines an object able to parse WebTrends(tm) Enhanced Log Format. That log format was defined by WebTrends(tm) for its Firewall Suite. It defines an extensible format that is now used by several packet filter and/or proxy firewall. The document describing that format is available from http://www.webtrends.com/partners/welfOverview.htm A list of products/vendor that supports this format can be found at http://www.webtrends.com/partners/firewall.htm You create a WELF parser object using the new() method: my $parser = new Lire::WELF(); To parse a WELF record you invoke the parser() method with the line containing the record as parameter: my $rec = $parser->parse( $line ); The $rec is an hash reference with the WELF field name used as keys and the value of the records as values. No value are interpreted or checked in any except for the following: =over 4 =item time The time field will be converted to epoch time =item quotation The quotation marks used when the value contains spaces are removed. =back =head2 WELF EXTENSIONS The parser also supports "extensions" to the format found in the field. =over =item port We will interpret correctly src and dst fields that have the port embededded in them: src=192.168.1.1:1037 =item interface A possible :IFNAME will also be interpreted as the interface name: dst=192.168.100.10:23:WAN =item timezone The time field may contains a time zone identifier: time="2001-12-02 12:34:12 UTC" =back =head2 Derived Fields The parser will generate a few 'derived' to complete the format. =over 4 =item src_port Will contain the src port portion of the dst field when SonicWall extensions are used. =item dst_port Will contain the interface portion of the dst field when SonicWall extensions are used. =item src_if Will contain the interface portion of the src field when SonicWall extensions are used. =item dst_if Will contain the interface portion of the dst field when SonicWall extensions are used. =back =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: WELF.pm,v 1.11 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Utils.pm��������������������������������������������������������������������0000644�0001750�0001750�00000064750�10460673256�013263� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Utils; use strict; use base qw/ Exporter /; use File::Spec; use Fcntl; use File::Basename; use Carp; use Socket; # for gethostbyaddr use Time::Local; use vars qw( @EXPORT_OK ); BEGIN { @EXPORT_OK = qw/ xml_encode latex_encode diff_lists tilde_expand tempfile tempdir tmpdir min max ratio ratio100 shell_quote indent file_content create_file sql_quote_name tree_apply item_index check_param check_object_param deep_copy host_by_addr is_url parse_url period_range unique text_for_width /; } =pod =head1 NAME Lire::Utils - Various general-purpose function. =head1 SYNOPSIS use Lire:Utils qw/ xml_encode /; =head1 DESCRIPTION This module defines several general purpose functions. No functions are exported by default, you have to specify the one you want to import in your namespace when you use the module. =head2 xml_encode( $str ) Converts standard the characters <,>,&," and ' to their XML entities. Example print XML_STREAM xml_encode( $value ); =cut sub xml_encode { my $value = $_[0]; $value =~ s/&/&/g; $value =~ s/</</g; $value =~ s/"/"/g; $value =~ s/'/'/g; return $value; } =pod =head2 latex_encode( $str ) Returns $str with all LaTeX special characters escaped. =cut sub latex_encode { my $str = $_[0]; $str =~ s/\\/--LIRE--BACKSLASH--/g; $str =~ s/([#\$&_%{}])/\\$1/g; $str =~ s/([~^])/\\$1\{\}/g; $str =~ s/(\[|\]|<|>)/\$$1\$/g; $str =~ s/--LIRE--BACKSLASH--/\$\\backslash\$/g; return $str; } =pod =head2 tilde_expand( $path ) Does tilde-expansion on a path, if possible. This means that paths of the form ~/foo are transformed to something like /home/user/foo, where "/home/user" is the content of the $HOME variable. Paths of the form ~otheruser/foo are translated similary by a passwd lookup. =cut sub tilde_expand { my $path = $_[0]; return $path if ord( $path ) != 126; # ascii code for ~ my ( $tilde, $rest ) = split( '/', $path, 2 ); my $user = substr( $tilde, 1 ); # skip the initial ~ if ( $user eq '' ) { croak('$HOME not set') unless exists $ENV{'HOME'}; $tilde = $ENV{'HOME'}; } else { my ( $name, $pass, $uid, $gid, $quota, $comment, $gecos, $dir) = getpwnam( $user ); $tilde = $dir if defined $dir; } $tilde .= "/$rest" if defined $rest; return $tilde; } =pod =head2 diff_lists( $list1, $list2 ) Compare two list, if the two list contains the same items (even if in different order) it returns undef. Otherwise an hash reference is returned which contains the list of new items in the 'new' key and the list of items to remove (to $list1 to make $list2) in the 'remove' key. =cut sub diff_lists { my ( $list1, $list2 ) = @_; croak "list1 param must be an array ref: $list1" unless ref $list1 eq 'ARRAY'; croak "list2 param must be an array ref: $list2" unless ref $list2 eq 'ARRAY'; # Sort the items my @list1 = sort @$list1; my @list2 = sort @$list2; my @new = (); my @remove = (); while ( @list1 && @list2 ) { my $d = $list1[0] cmp $list2[0]; if ( $d < 0 ) { push @remove, shift @list1; } elsif ( $d == 0 ) { shift @list1; shift @list2; } else { push @new, shift @list2; } } # All other elements are removed push @remove, @list1; push @new, @list2; if ( @remove || @new ) { return { 'remove' => \@remove, new => \@new }; } else { return undef; } } =pod =head1 PORTABILITY FUNCTIONS For portability across Perl versions, this module defines some functions that are usually found in the latest version of Perl but that may not be present in some old ones (the oldest version of Perl we support is 5.00503). =head2 tmpdir() This method (provided by recent versions of File::Spec) returns where temporary files should go. =cut sub tmpdir { return ( File::Spec->can( "tmpdir" ) ? return File::Spec->tmpdir : _tmpdir() ); } sub _tmpdir { foreach my $dir ( $ENV{'TMPDIR'}, "/var/tmp", "/tmp" ) { return $dir if -r $dir && -w $dir; } croak "no writeable temporary directory available\n"; } =pod =head2 tempfile() my $fh = tempfile(); my $fh = tempfile( $template, 'SUFFIX' => ".txt" ) my ( $fh, $name ) = tempfile( $template, 'SUFFIX' => ".dlf" ); This is a wrapper around the File::Temp::tempfile Perl function when available, and it offers a home grown version which should be safe when it isn't available. The only difference is that the file will always be created in the directory specified in $ENV{'TMPDIR'} or F</tmp> when unset. The first argument to the function should be a template name containing at least 6 X (i.e. tempXXXXXX) which will get replaced to generate a random name. When no arguments are passed, a default template of tempfileXXXXXX will be use. Other options can be passed to the function by using 'key' => value pairs. The only option understood by the home grown version is SUFFIX which will be appended to the filename. (The Perl version understands more options, but you shouldn't use them for compatibility.) The function takes precautions against symlink attacks (and creates the file with readwrite permission for the owner only). It will die(), if it fails to create a temporary file after 10 attempts. (This shouldn't happen unless someone is seriously trying to race with us.) The function will return in scalar context an anonymous file handle opened on the temporary file. The temporary file was unlinked after creation and will thus be deleted automatically when you close the file handle. When used in an array context, the function will return a file handle and the path to the temporary file (this can be useful for debugging purpose or when you can't pass the file by file handle to another process). In this case, the file should be deleted manually. =cut my @chars = ( 'a' .. 'z', 'A' .. 'Z', 0 .. 9, ); sub tempfile { eval "use File::Temp"; if ( $@ ) { return _tempfile( @_ ); } elsif ( @_ ) { return File::Temp::tempfile( @_, 'DIR' => tmpdir() ); } else { return File::Temp::tempfile( 'DIR' => tmpdir() ); } } sub _tempfile { # Poor's man tempfile, File::Temp is only part of Perl 5.6.1 my ($tmpl, %args); if (@_) { ($tmpl, %args) = @_; $tmpl = tmpdir() . "/" . basename( $tmpl ); } else { $tmpl = tmpdir() . "/tempfileXXXXXX"; } # Try 10 times to open a file for (0..10) { $tmpl =~ s/X/$chars[rand @chars]/ge; $tmpl .= $args{'SUFFIX'} if defined $args{'SUFFIX'}; if ( sysopen( my $fh, $tmpl, O_RDWR|O_CREAT|O_EXCL, 0600 ) ) { binmode $fh; unlink $tmpl unless wantarray; return wantarray ? ($fh, $tmpl): $fh; } sleep 1; } die "tempfile(): somebody is trying to race with us!\n"; } =pod =head2 tempdir() my $dir = tempdir(); my $dir = tempdir( $template ) This is a wrapper around the File::Temp::tempdir Perl function when available, and it offers a home grown version which should be safe when itsn't available. The only difference is that the directory will always be created in the directory specified in $ENV{'TMPDIR'} or F</tmp> when unset. The first argument to the function should be a template name containing at least 6 X (i.e. tempXXXXXX) which will get replaced to generate a random name. When no arguments are passed, a default template of tempdirXXXXXX will be used. Other options can be passed to the function by using 'key' => value pairs. The only option understood by the home grown version is DIR which specifies where the directory will be created (The Perl version understands more options, but you shouldn't use them for compatibility.) The function takes precautions against symlink attacks (and create the file with readwrite permission for the owner only). It will die(), if it fails to create a temporary directory after 10 attempts. (This shouldn't happen unless someone is seriously trying to race with us.) The function will return the name of the directory that was created. =cut sub tempdir { eval "use File::Temp;"; if ( $@ ) { return _tempdir( @_ ); } elsif (@_) { return File::Temp::tempdir( @_, 'DIR' => tmpdir() ); } else { return File::Temp::tempdir( 'DIR' => tmpdir() ); } } sub _tempdir { my $self = $_[0]; # Poor's man tempdir, File::Temp is only part of Perl 5.6.1 my ($tmpl, %args); if (@_) { ($tmpl, %args) = @_; $tmpl = tmpdir() . "/" . basename( $tmpl ); } else { $tmpl = tmpdir() . "/tempdirXXXXXX"; } # Try 10 times to create a directory for (0..10) { $tmpl =~ s/X/$chars[rand @chars]/ge; if ( mkdir $tmpl, 0700 ) { return $tmpl; } sleep 1; } croak "tempdir() somebody is trying to race with us!\n"; } =pod =head2 min() my $least = min(@values); my $least = min($a,$b,$c); =head2 max() my $greatest = max(@values); my $greatest = max($a,$b,$c); These find the smallest or largest value in a list of numbers. An empty list will return undef. Undef values are ignored and will only be returned if the list is empty or contains only undefined value. =cut sub min { my $min = undef; foreach my $x ( @_ ) { next unless defined $x; if ( defined $min ) { $min = $x if $x < $min; } else { $min = $x; } } return $min; } sub max { my $max = undef; foreach my $x ( @_ ) { next unless defined $x; if ( defined $max ) { $max = $x if $x > $max; } else { $max = $x; } } return $max; } =pod =head2 ratio( $dividend, $divisor ) Returns $divivend / $divisor and returns "NaN" when $divisor is equals to 0. It rounds the result to the second decimal. =cut sub ratio { my ( $dividend, $divisor ) = @_; if ( $divisor ) { return sprintf "%.2f", $dividend / $divisor; } else { return "NaN"; } } =pod =head2 ratio100( $part, $total ) Returns as a percentage $part on $total. This function is safe to use when $total is equal to 0 (it will returns NaN). The percentage is rounded to the first decimal. =cut sub ratio100 { my ( $dividend, $divisor ) = @_; if ( $divisor ) { return sprintf "%.1f", ($dividend / $divisor) * 100; } else { return "NaN"; } } =pod =head2 shell_quote($string) Return $string in a format that make it safe to hand out to the shell so that metacharacters are not interpreted by the shell. This is done by returning $string wrapped in single quotes and escaping the single quotes contained in the $string. =cut sub shell_quote { my $string = $_[0]; if (defined $string ) { # Make sure that there is no way to # escape the shell single quotes $string =~ s/'/'\\''/g } else { $string = ''; } return "'" . $string . "'"; } =pod =head2 indent( $string, [ $count ] ) Return $string, indented by $count spaces. If $count is not specified, a default of 2 will be assumed. =cut sub indent { my ( $text, $step ) = @_; return '' unless $text; $step = 2 unless defined $step; my @lines = split( /\n/, $text ); my $indented = join( "\n", map( { ' ' x $step . $_ } @lines ) ); $indented .= "\n" if $text =~ m/\n$/; return $indented; } =pod =head2 check_param( $param, $name, [ $regex | $coderef, $msg ] ) Check that param "$name" is not undefined, and that it optionally match the given regexp. Validation can also be achieved through a code reference passed as the third parameter. The convention in this case is that the subroutine will return a boolean indicating whether $param is valid or not. Examples: check_param( $req_param, 'req_param' ); check_param( $param_string, 'param_string', qr/^[a-z]+$/ ); check_param( $integer, 'integer', qr/^[0-9]+$/, "not a valid integer" ); check_param( $bool, 'bool', sub { return $_[0] }, "boolean was false" ); =cut sub check_param { my ( $param, $name, $regex, $msg ) = @_; my ( $package, $filename, $line ) = caller(); die "check_param needs at least 2 arguments: a parameter, the parameter\'s name at $filename:$line\n" unless ( @_ >= 2 ); die "parameter 'name' is not a valid name: '$name' at $filename:$line\n" unless ( $name =~ m/^[a-zA-Z0-9_]+$/ ); ( $package, $filename, $line ) = caller( 1 ); die "missing '$name' parameter at $filename:$line\n" unless defined $param; if ( defined $regex ) { if ( ref $regex eq 'CODE' ) { die ( defined $msg ? "$msg: '$param' at $filename:$line\n" : "'$name' parameter value ('$param') doesn't validate with subroutine at $filename:$line\n" ) unless ( $regex->( $param ) ); } else { die ( defined $msg ? "$msg: '$param' at $filename:$line\n" : "'$name' parameter doesn't match '$regex': '$param' at $filename:$line\n" ) if ( $param !~ $regex ); } } return; } =pod =head2 check_param( $instance, $name, $class ) Check that param "$instance" is a valid of one or more classes specified in the 'class' parameter. The latter being either a string or a reference to an array containing one or more such strings. Examples: check_param( $object, 'object', 'Wawa::Class' ); check_param( $object, 'object', [ 'Wawa::Class', 'Other::Class' ] ); =cut sub check_object_param { my ( $instance, $name, $class ) = @_; my ( $package, $filename, $line ) = caller(); die "check_object_param needs 3 arguments: an object, the object parameter's name, the object's class name at $filename:$line\n" unless ( @_ == 3 ); die "parameter 'name' is not a valid name: '$name' at $filename:$line\n" unless ( $name =~ m/^[a-zA-Z0-9_]+$/ ); $class = [ $class ] unless ( ref $class eq 'ARRAY' ); die "parameter 'class' should contain at least one class name at $filename:$line\n" unless ( @{$class} > 0 ); foreach my $cl ( @{$class} ) { die "parameter 'class' contains an invalid class name: '$cl' at $filename:$line\n" unless ( $cl =~ m/^[a-zA-Z0-9_]+(::[a-zA-Z0-9_]+)*$/ ); } ( $package, $filename, $line ) = caller( 1 ); die "missing '$name' parameter at $filename:$line\n" unless defined $instance; foreach my $cl ( @{$class} ) { return if UNIVERSAL::isa( $instance, $cl ); } if ( @{$class} == 1 ) { die "'$name' parameter should be a '$class->[0]' instance, not '$instance' at $filename:$line\n"; } else { my $string = join "', '", @{$class}[0..@{$class}-2]; $string .= "' or '$class->[-1]" ; die "'$name' parameter should be a '$string' instance, not '$instance' at $filename:$line\n"; } } =pod =head2 sql_quote_name( $name ) =cut sub sql_quote_name { my $name = $_[0]; return ( $name =~ /[-:.]/ ) ? '"' . $name . '"' : $name; } =pod =head2 tree_apply( $root, $children_func, $apply_func ) Preorder processsing =cut sub tree_apply { my ( $root, $children_func, $apply_func ) = @_; check_param( $root, 'root' ); check_param( $children_func, 'children_func' ); check_param( $apply_func, 'apply_func' ); my $results = [ $root->$apply_func() ]; my $children = $root->$children_func(); while ( @$children ) { my $node = shift @$children; push @$results, $node->$apply_func(); unshift @$children, @{$node->$children_func()}; } return $results; } =pod =head2 item_index( $array_ref, $item ) Returns the index of $item in $array. It returns undef if the item isn't found. $array_ref should be an ARRAY reference and $item should be a non-null scalar. =cut sub item_index { my ( $array, $item ) = @_; check_param( $array, 'array' ); croak "'array' should be an array ref, not '$array'" unless ( ref $array eq 'ARRAY' ); check_param( $item, 'item' ); for ( my $i = 0; $i < @$array; $i++ ) { return $i if ( $array->[$i] eq $item ); } return undef; } =pod =head2 deep_copy( $object, [$exclusion] ) Makes a recursive copy of $object. Cyclic references are maintained in the copy. Optionnally, an array ref of packages for which the objects shouldn't be deeply copied can be provided. =cut sub deep_copy { my ( $object, $exclusions ) = @_; check_param( $object, 'object' ); croak "'exclusions' should be an array reference, not '$exclusions'" if defined $exclusions && ref $exclusions ne 'ARRAY'; $exclusions ||= []; return _deep_copy( $object, {}, $exclusions ); } sub _deep_copy { my ( $object, $seen, $exclusions ) = @_; return $object unless ref $object; return $seen->{$object} if exists $seen->{$object}; if ( ref $object eq 'SCALAR' || ref $object eq 'REF' ) { return _clone_scalar_ref( $object, $seen, $exclusions ); } elsif ( ref $object eq 'ARRAY' ) { return _clone_array_ref( $object, $seen, $exclusions ); } elsif ( ref $object eq 'HASH' ) { return _clone_hash_ref( $object, $seen, $exclusions ); } elsif ( ref $object eq 'Regexp' ) { # This is a read-only object return $object; } elsif ( UNIVERSAL::isa( $object, 'UNIVERSAL' ) ){ # blessed object return _clone_object( $object, $seen, $exclusions ); } else { croak "ref type unsupported by deep_copy(): $object"; } } sub _clone_scalar_ref { my ( $scalar_ref, $seen_refs, $exclusions ) = @_; my $scalar; $seen_refs->{$scalar_ref} = \$scalar; $scalar = _deep_copy( $$scalar_ref, $seen_refs, $exclusions ); return \$scalar; } sub _clone_array_ref { my ( $array_ref, $seen_refs, $exclusions ) = @_; my @array_copy = (); $seen_refs->{$array_ref} = \@array_copy; for my $elmnt ( @$array_ref ) { push @array_copy, _deep_copy( $elmnt, $seen_refs, $exclusions ); } return \@array_copy; } sub _clone_hash_ref { my ( $hash_ref, $seen_refs, $exclusions ) = @_; my %hash = (); $seen_refs->{$hash_ref} = \%hash; while ( my( $key, $value ) = each %$hash_ref ) { $hash{$key} = _deep_copy( $value, $seen_refs, $exclusions ); } return \%hash; } sub _clone_object { my ( $object, $seen, $exclusions ) = @_; foreach my $excl ( @$exclusions ) { return $object if $object->isa( $excl ); } if ( index( $object, '=SCALAR(' ) >= 0 ) { return bless( _clone_scalar_ref( $object, $seen, $exclusions ), ref $object); } elsif ( index( $object, '=HASH(' ) >= 0 ) { return bless( _clone_hash_ref( $object, $seen, $exclusions ), ref $object); } elsif ( index( $object, '=ARRAY(' ) >= 0 ) { return bless( _clone_array_ref( $object, $seen, $exclusions ), ref $object); } else { croak "unsupported object storage: '$object'"; } } # could better use a Perl interface to getnameinfo(3) sub host_by_addr { ## perldoc -f gethostbyaddr ## # gethostbyaddr(3) ## # See also: logresolve, from e.g. the Debian apache-utils package ## ## # $? holds: ## # ## # HOST_NOT_FOUND ## # The specified host is unknown. ## # ## # NO_ADDRESS or NO_DATA ## # The requested name is valid but does not have an IP address. ## # ## # NO_RECOVERY ## # A non-recoverable name server error occurred. ## # ## # TRY_AGAIN ## # A temporary error occurred on an authoritative name server. Try ## # again later. my $ip = $_[0] or die "usage: gethostbyaddr IPv4address\n"; my $iaddr = inet_aton($ip) or die "$ip isn't an IPv4 address\n"; my $name; unless ( $name = gethostbyaddr( $iaddr, AF_INET ) ) { warn "can't resolve $ip: $? ($!)\n"; $name = undef; } return $name; } =pod =head2 unique( $list ) Returns an array reference with the duplicates elements of $list removed. =cut sub unique { my $list = $_[0]; check_object_param( $list, 'list', 'ARRAY' ); my $unique = []; my %cache = (); foreach my $element ( @$list ) { push @$unique, $element unless exists $cache{$element}; $cache{$element} = 1; } return $unique; } =pod =head2 text_for_width( $text, $width ) Returns a stripped-down representation of 'text', ensuring its length is shorter or equal to 'width'. If the original text already fits the given width, it is returned unchanged, otherwise, it is shortened and '...' is put in the middle to indicate the cut. =cut sub text_for_width { my ( $text, $width ) = @_; check_param( $text, 'text' ); check_param( $width, 'width', sub { return ( $_[0] =~ m/^[0-9]+$/ && $_[0] >= 5 ) }, "'width' should be a positive, greater than or equal to 5, integer" ); my $length = length( $text ); return $text if $length <= $width; my $segment = ( $width - 3 ) / 2; my $start = substr( $text, 0, $segment ); $start =~ s/\s*$//g; my $end = substr( $text, $length - $segment ); $end =~ s/^\s*//g; return $start . '...' . $end; } =pod =head2 is_url( $string ) Determines whether $string is a url or not, returning 'true' or 'false' as result code. =cut sub is_url { my $string = $_[0]; check_param( $string, 'string' ); return $string =~ m@^[a-zA-Z0-9]+://@ || 0; } =pod =head2 parse_url( $string ) Returns an hash reference containing keys for the following URL parts: 'scheme', 'host', 'port', 'path', 'query', 'fragment'. The value will be empty if this wasn't present in the URL. This function is somewhat 'http' biased and one should use the URI module for full blown URI parsing. The function dies if the URL cannot be parsed. =cut sub parse_url { check_param( $_[0], 'url' ); # e.g. # http://ds.internic.net/instructions/overview.html#WARNING my ( $scheme, $authority, $path, $query, $fragment) = ( $_[0] =~ m/^ (?: ([^:\/?\#]+): # scheme )? (?: \/\/([^\/?\#]*) # authority )? ([^?\#]*) # path (?: \?([^\#]*) # query )? (?: \#(.*) # fragment )?$/x ) or die "invalid url: '$_[0]'"; # fullblown # # authority = server | reg_name # server = [ [ userinfo "@" ] hostport ] # hostport = host [ ":" port ] # host = hostname | IPv4address # # is not yet supported my ( $host, $port ); ( $host, $port ) = $authority =~ m/^([-\.a-zA-Z0-9]+)(?::(\d+))?$/ if defined $authority; return { 'scheme' => $scheme, 'host' => $host, 'port' => $port, 'path' => $path, 'query' => $query, 'fragment' => $fragment }; } =pod =head2 file_content( $filename ) Returns the content of $filename. Dies if an error occurs. =cut require Lire::Error; sub file_content { my $file = $_[0]; check_param( $file, 'filename' ); open my $fh, $file or croak( Lire::Error::file_not_readable( $file ) ); local $/ = undef; my $content = <$fh>; close $fh; return $content; } =pod =head2 create_file( $filename, [$content], [$utf8_encoding] ) Creates file $filename with $content. The $utf8_encoding flag specifies whether you want to keep strings in their UTF-8 encoding with versions of Perl that supports it (5.8.0 and above). =cut require Lire::I18N; sub create_file { my ( $filename, $content, $utf8_encoding ) = @_; check_param( $filename, 'filename' ); $content = "" unless defined $content; open( my $fh, '>', $filename ) or croak "error creating '$filename': $!"; Lire::I18N::set_fh_encoding( $fh, 'utf-8' ) if $utf8_encoding; print $fh $content; close $fh; return; } =pod =head2 period_range( $period, $time ) Returns an array reference containing the starting and ending boundaries for the $period that includes $time. $period should be one of 'hourly', 'daily', 'weekly', 'monthly' or 'yearly'. $time should be in seconds since epoch. =cut require Lire::WeekCalculator; sub period_range { my ( $period, $time ) = @_; check_param( $period, 'period', qr/^(hourly|daily|weekly|monthly|yearly)$/, "'period' parameter should be one of 'hourly', 'daily', 'weekly', 'monthly' or 'yearly'" ); check_param( $time, 'time', qr/^\d+$/, "'time' paremeter should be seconds since epoch" ); my ( $hour, $day, $month, $year ) = (localtime( $time || time() ))[2..5]; if ( $period eq 'hourly' ) { my $start = timelocal( 0, 0, $hour, $day, $month, $year ); return [ $start, $start + 3600 ]; } elsif ( $period eq 'daily' ) { my $start = timelocal( 0, 0, 0, $day, $month, $year ); return [ $start, $start + 3600*24 ]; } elsif ( $period eq 'weekly' ) { my $calc = new Lire::WeekCalculator(); my $week_no = $calc->week_number( $time ); my $start = $calc->week_start( $year, $week_no ); return [ $start, $start + 86400*7 ]; } elsif ( $period eq 'monthly' ) { my $start = timelocal( 0, 0, 0, 1, $month, $year ); if ( $month == 11 ) { return [ $start, timelocal( 0, 0, 0, 1, 0, $year+1 ) ] } else { return [ $start, timelocal( 0, 0, 0, 1, $month + 1, $year ) ] } } elsif ( $period eq 'yearly' ) { return [ timelocal( 0, 0, 0, 1, 0, $year ), timelocal( 0, 0, 0, 1, 0, $year+1 ) ] } } # keep perl happy 1; __END__ =pod =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Joost van Baal <joostvb@logreport.org> Wessel Dankers <wsl@logreport.org> Wolfgang Sourdeau <wolfgang@logreport.org> =head1 VERSION $Id: Utils.pm,v 1.67 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001, 2002, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������lire-2.1.1/all/lib/Lire/DlfConverter.pm�������������������������������������������������������������0000644�0001750�0001750�00000013551�10460673254�014547� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::DlfConverter; use strict; use base qw/Lire::Plugin/; use Carp; =pod =head1 NAME Lire::DlfConverter - Base interface of all DLF converters. =head1 SYNOPSIS use base qw/ Lire::DlfConverter /; =head1 DESCRIPTION This package defines the interface that must be implemented by all DLF Converters. All the methods defined in this package will throw a 'method not implemented' exception if they are called. =head1 META INFORMATION METHODS These methods provides information to the Lire framework about the DLF converter. =head2 name() Returns the name of the DLF converter, i.e. the service's (aka log format) name. E.g. C<combined> =cut sub name { croak "name() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 title() Returns a more human friendly name for the DLF Converter. E.g. C<Combined Log Format DLF Converter> =cut sub title { croak "title() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 description() Returns a DocBook XML based documentation of the DLF Converter. E.g. <para>This DLF converter can be used to process log file in the Combined Log Format to the www DLF schema.</para> =cut sub description { croak "description() not implemented by ", ref $_[0] || $_[0]; } sub type { return 'dlf_converter' } =pod =head2 schemas() Returns a list of DLF schemas for which DLF records can be written from the data contained in the log file. E.g. For the combined DLF converters, that would be 'www'. For the 'nms' converter that could be C<qw/daemon email/> which means that the DLF converter writes DLF records in the hypothetical C<daemon> schema (server start, stops, restarts, etc.) and the email schema. This should only contains 'base' (aka superservice) schemas. No extended or derived schema's name should appear in that list. (Those are reserved for the analyzers). =cut sub schemas { croak "schemas() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 handle_log_lines() This method should returns true if the DlfConverter processes line-oriented log file. This is the default. If this method returns false, only the process_log_file() method will be called, otherwise the process_log_line() method is used for every input lines. =cut sub handle_log_lines { 1 } =head1 Implementation methods These are the methods where the DLF converter work is done. The init_dlf_converter() method will be called once before any processing occurs. Afterwards, process_log_line() will be called once for every line that was marked for log continuation and for every line contained in the log file. The finish_conversion() method will be called once all lines are processed. Any exceptions (uncaught die) that occur during any of the methods will abort the conversion process. =head2 init_dlf_converter( $process, [$config] ) This method will be called by the framework before processing the log file. This method should be used by the converter to initialize its state. The $process parameter contains the Lire::DlfConverterProcess object which is controlling the conversion process. The $config parameter contains configuration data that was specified in the ImportJob for that converter. To register configuration specification for you DlfConverter, you just need to define a configuraiton specification under the name I<converter_name>_properties. This should be either a RecordSpec or ObjectSpec. =cut sub init_dlf_converter { croak "init_dlf_converter() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 process_log_file( $process, $fd ) This method is called so that the converter can convert the data contained in the $fd file handle to DLF. This method is only used when the handle_log_lines() method returned false. $process contains a reference to the Lire::DlfConverterProcess object which controls the conversion process and defines the API to write DLF and report errors. =cut sub process_log_file { croak "process_log_file() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 process_log_line( $process, $line ) This method is called by the framework once for each log line present in the log file. This method is only called if the handles_log_lines() method returnes true. $process is a reference to the Lire::DlfConverterProcess object. This object defines a method to report errors, save lines for continuation purposes and writes DLF records. $line contains the log line which should be processed with the end of line removed. =cut sub process_log_line { croak "process_log_line() not implemented by ", ref $_[0] || $_[0]; } =pod =head2 finish_conversion( $dlf_store ) This method is called once by the framework once all log lines were processed. It can be use by the converter to write any DLF records that could be remaining because of a stateful analysis. =cut sub finish_conversion { croak "finish_conversion() not implemented by ", ref $_[0] || $_[0]; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfConverterProcess(3pm), Lire::DlfStore(3pm), Lire::ImportJob(3pm), Lire::PluginManager(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: DlfConverter.pm,v 1.12 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002, 2003, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Time.pm���������������������������������������������������������������������0000644�0001750�0001750�00000025526�10460673256�013057� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Time; use strict; use base qw/ Exporter /; use Time::Local; use Time::Timezone; use Carp; use vars qw/ @EXPORT /; BEGIN { @EXPORT = qw/ date2cal syslog2cal clf2cal cal2rfc cal2ymdhms getMonthName /; } =pod =head1 NAME Lire::Time - parses and prints date in formats common to many log files. =head1 SYNOPSIS use Lire::Time qw/ syslog2cal /; my @ltime = localtime; while ( <LOGFILE> ) { #... my $time = syslog2cal( $m, $d, $t, \@ltime ); } =head1 DESCRIPTION This module supplies many functions to parse dates in formats that you are likely to encounter in log files. It also offers many functions to format epoch time in useful format. =head2 NOTE ABOUT FUNCTION EXPORT Altough all documented functions are exported by default to the caller namespace, you should explicitely import the functions you require since exporting by default isn't recommanded by the perl modules guidelines. =cut # convert Jan and friends to localtime(3) tm_mon thingies my %monthnumbers = ( 'jan' => 0, 'feb' => 1, 'mar' => 2, 'apr' => 3, 'may' => 4, 'jun' => 5, 'jul' => 6, 'aug' => 7, 'sep' => 8, 'oct' => 9, 'nov' => 10, 'dec' => 11, ); my @monthnames = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/; my @daynames = qw/Sun Mon Tue Wed Thu Fri Sat/; # convert Mar 20 09:13:32 to ($tm_sec, $tm_min, $tm_hour, $tm_day, $tm_month) sub syslog2tm($$$) { my $sub = 'syslog2tm'; # month name (e.g. May) we tolerate e.g. jan # day, possibly 0 padded # time as hh:mm:ss or hh:mm:ss.sss my ( $month, $day, $time ) = @_; # process $time # We tolerate an extra : at the end of the time. # HH:MM:SS[.MSEC]: my ( $hour, $min, $sec, $msec ) = $time =~ /^(\d\d):(\d\d):(\d\d)(\.\d+)?:?$/ or croak "$sub time '$time' should be hh:mm:ss[.msec]:?"; # convert from string to integers my $tm_hour = $hour + 0; my $tm_min = $min + 0; my $tm_sec = $sec + 0; # get rid of leading zero # process day my $tm_day = $day + 0; # process month my $tm_month; if ($month =~ /\d+/) { $tm_month = $month; } else { $tm_month = $monthnumbers{ lc $month }; die("$sub cannot get monthnumber from monthname '$month'") unless defined $tm_month; } return [ $tm_sec, $tm_min, $tm_hour, $tm_day, $tm_month ]; } # iso 8601:1988 5.3.3.1 , # http://doc.mdcc.cx/~joostvb/doc/iso-8601:1988-representation_of_dates_and_times.pdf sub tzdiff2sec($) { # e.g. +0100 or -0900 ; +hh:mm, +hhmm, or +hh my ( $sign, $hour, $min ) = $_[0] =~ /^([+-])?(\d\d):?(\d\d)?$/ or croak "invalid tzdiff format: $_[0]. It must looks like +0100 or -01:00\n"; $sign ||= "+"; $hour ||= 0; $min ||= 0; my $sec = $hour * 60 * 60 + $min * 60; $sec *= -1 if $sign eq '-'; return $sec; } =pod =head1 DATE PARSING FUNCTIONS This module includes several functions that convert between a more human readable date format and UNIX epoch time. All parsing functions will return the number of seconds since Jan 1 1970 00:00:00 UTC and will die() when passed invalid arguments. =head2 date2cal() my $time = date2cal( $year, $month, $day, $time, [$timezone] ); my $time = date2cal( "2001 Mar 20 09:32:29 +0100" ); This function will convert a date in the date(1) default output format to UNIX epoch time. The function accepts either the date in a string or splitted on whitespace. If the timezone component is omitted, the local timezone is assumed (usually based on the value of the TZ environment variable). =cut # Tue, 20 Mar 2001 09:46:40 +0100 is Tue Mar 20 08:46:50 UTC 2001 # # http://www.cl.cam.ac.uk/~mgk25/iso-time.html says: # # 12:00 UTC (aka 12:00Z) = 13:00+01:00 = 0700-0500 # # There exists no international standard that specifies abbreviations for # civil time zones like CET, EST, etc. # # nice to handle apache stuff like [18/Mar/2001:16:00:26 +0100] # sub date2cal($;$$$$) { my $sub = 'date2cal'; @_ = split /\s+/, $_[0] if @_ == 1; croak "$sub give 1, 4 or 5 args" if @_ < 4; # tzdiff e.g. +0100 or -0900 ; +hh:mm, +hhmm, or +hh my ($year, $month, $day, $time, $tzdiff ) = @_; if ( defined $tzdiff ) { $tzdiff = tzdiff2sec( $tzdiff ); } else { $tzdiff = tz_local_offset(); } my $tm = syslog2tm($month, $day, $time); # tm still has to get fixed with respect to $tzdiff my $tm_year = $year - 1900; push @$tm, ($tm_year); # We use timegm because the time will be modified by tzdiff my $cal = timegm( @$tm ); # If tzdiff is undefined, it will use the current time zone return $cal - $tzdiff; } =pod =head2 syslog2cal() my $time = syslog2cal( $month, $day, $time, $local_tm_ref ); my $time = syslog2cal( "Mar 11 13:21:00", $local_tm_ref ); This function will convert a date in the syslog default output format to UNIX epoch time. The function accepts either the date in a string or splitted on whitespace. Since the syslog format doesn't contain timezone information, the local timezone is assumed (usually determined by the TZ environment variable). The last argument is a reference to an array returned by localtime(). my $local_tm_ref = [localtime()]; It is used to determine the year. =cut sub syslog2cal($$;$$) { my $sub = 'syslog2cal'; @_ = ( split( /\s+/, $_[0]), $_[1] ) if (@_ == 2 ); # month name (e.g. May) we tolerate e.g. jan # day, possibly 0 padded # time as hh:mm:ss or hh:mm:ss.sss # reference point of now, to guess the year my ( $month, $day, $time, $now_ltime ) = @_; croak "$sub ltime arg should be a reference to array as returned by localtime()" unless ref $now_ltime eq 'ARRAY' && @$now_ltime == 9; my $tm = syslog2tm($month, $day, $time ); # Guess the year based on the difference between now and tm my $tm_year; my $now_year = $now_ltime->[5]; my $now_month = $now_ltime->[4]; my $now_day = $now_ltime->[3]; if ( $tm->[4] < $now_month ) { # Current year, unless the month is january, the day the first # and now is the last day of december if ( $tm->[4] == 0 && $tm->[3] == 1 && $now_month == 11 && $now_day == 31) { $tm_year = $now_year + 1; } else { $tm_year = $now_year; } } elsif ( $tm->[4] == $now_month ) { # Current year if the day is in the past, today, or one day ahead # last year otherwise if ( $tm->[3] <= ($now_day + 1) ) { $tm_year = $now_year; } else { $tm_year = $now_year - 1; } } elsif ( $tm->[4] == $now_month + 1 && $tm->[3] == 1 ) { # One month ahead: this means last year, unless we are on the # last day of the month and it is the first day of the month $tm_year = $now_year - 1; if ( $now_month =~ /^(0|2|4|6|7|9|11)$/ && $now_day == 31) { # Last day of jan, march, may, jul, aug, oct, dec $tm_year = $now_year; } elsif ( $now_month =~ /^(3|5|8|10)$/ && $now_day == 30) { # Last day of apr, jun, sep, nov $tm_year = $now_year; } elsif ( $now_day == 28 || $now_day == 29 ) { # Last day of february $tm_year = $now_year; } } else { # Last year $tm_year = $now_year - 1; } return timelocal( @$tm, $tm_year ); } =pod =head2 clf2cal() my $time = clf2cal( "[18/Mar/2001:15:59:30 +0100]" ); This function will convert a date as found in Common Log Format to UNIX epoch time. =cut sub clf2cal($) { my $sub = 'clf2cal'; my ($time) = @_; # ($dom, $month, $year, hour:min:sec, $tzdiff) my @date = $time =~ /^\[(\d+)\/(\w+)\/(\d{4}):(\d{2}:\d{2}:\d{2})\s+([-+][:\d]+)\]$/ or croak "$sub time '$time' should be something like [18/Mar/2001:15:59:30 +0100]\n"; # year month day time tzdiff return date2cal($date[2], $date[1], $date[0], $date[3], $date[4]); } =pod =head1 DATE FORMATING FUNCTIONS This module includes some functions to convert date in UNIX epoch time to some more human readable output. All functions will die() when passed invalid arguments. =head2 cal2rfc() print cal2rfc( $time ); This function will convert a date in UNIX epoch time to the RFC822 format (used in email, for example). A RFC822 date looks like Wed, 30 May 2001 12:45:13 +0000 The timezone offset specification will correspond to the local timezone (usually determined by the TZ environment variable). =cut sub cal2rfc($) { my $sub = 'cal2rfc'; my $time = $_[0]; my ( $tm_sec, $tm_min, $tm_hour, $tm_mday, $tm_mon, $tm_year, $tm_wday ) = localtime $time ; my $off = tz_local_offset; my $tzoff = sprintf("%+05d", int($off / 3600) * 100 + $off % 60); return $daynames[$tm_wday] . ", $tm_mday " . $monthnames[$tm_mon] . " " . ($tm_year + 1900) . " " . ($tm_hour < 10 ? '0' : '') . "$tm_hour:" . ($tm_min < 10 ? '0' : '') . "$tm_min:" . ($tm_sec < 10 ? '0' : '') . "$tm_sec " . $tzoff; } =pod =head2 cal2ymdhms() print cal2ymdhms( $time ); This function converts a date in UNIX epoch time to a string of the form: YYYYMMDDHHMMSS This representation will correspond the time in the local timezone (usually determined by the TZ environment variable.) =cut sub cal2ymdhms($) { my $sub = 'cal2ymdhms'; my ( $tm_sec, $tm_min, $tm_hour, $tm_mday, $tm_mon, $tm_year ) = localtime $_[0]; $tm_mon++; return '' . ($tm_year + 1900) . ($tm_mon < 10 ? '0' : '') . $tm_mon . ($tm_mday < 10 ? '0' : '') . $tm_mday . ($tm_hour < 10 ? '0' : '') . $tm_hour . ($tm_min < 10 ? '0' : '') . $tm_min . ($tm_sec < 10 ? '0' : '') . $tm_sec; } =pod =head2 getMonthName() print getMonthName( 0 ); # Gives 'Jan' This function takes as parameter a number (0-11) representing the month (as returned by localtime() for example) and will return the English abbreviated name of that month ( Jan, Feb, etc. ). =cut sub getMonthName($) { my $sub = 'getMonthName'; my ( $month ) = @_; croak "$sub month should be between 0 and 11" unless $month >= 0 && $month <= 11; return $monthnames[$month]; } # keep perl happy 1; __END__ =pod =head1 AUTHOR Joost van Baal <joostvb@logreport.org> =head1 VERSION $Id: Time.pm,v 1.10 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2000-2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Config.pm�������������������������������������������������������������������0000644�0001750�0001750�00000023621�10460673254�013356� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Config; use strict; use vars qw/ $VERSION $PACKAGE $SINGLETON /; use Lire::Config::Build qw(ac_info ac_path); use Carp; =pod =head1 NAME Lire::Config - import Lire configuration variables to perl =head1 SYNOPSIS use Lire::Config; Lire::Config->init(); my $cfg->value = Lire::Config->get( 'lr_schemas_path' ); my $var = Lire::Config->get_var( 'lr_schemas_path' ); =head1 DESCRIPTION This package provides the API to access the Lire configuration. =head1 METHODS These methods can be called directly on a Lire::Config instance or the Lire::Config package itself. In the last case, it is the same thing as calling the method on the object returned by the instance() method. =cut $SINGLETON = new Lire::Config::XMLFilesConfig(); sub lire_program_config_init { $SINGLETON->init(); init_vars(); } sub init_vars { # VERSION does not hold this module's version, but the Lire version. # ($VERSION) = '$Release:$' =~ m!Release: ([.\d]+)!; $VERSION = ac_info('VERSION'); $PACKAGE = ac_info('PACKAGE'); } =pod =head2 instance() Returns the singleton Lire::Config object from which configuration can be queried. =cut sub instance { return $SINGLETON; } BEGIN { no strict 'refs'; # Autogenerate methods which delegates to the singleton. foreach my $method ( qw/ init config_spec config_spec_path add_config_spec_path_dir del_config_spec_path_dir add_config_path add_config_file del_config_file config_files get_config_file get get_var / ) { *{$method} = sub { my $pkg = shift; $SINGLETON->$method( @_ ) }; } } package Lire::Config::XMLFilesConfig; use base qw/ Lire::Config /; use Lire::Config::Parser; use Lire::Config::SpecParser; use Lire::Utils qw/ tilde_expand check_param /; use Lire::Error qw/ directory_not_readable /; use Lire::Config::Build 'ac_path'; use Carp; sub new { my $proto = shift; my $class = ref( $proto ) || $proto; my $self = bless { '_config_spec_dirs' => [ ac_path('datadir', 'PACKAGE') . "/config-spec" ], '_config_files' => [], '_parsed_config' => {}, '_defaults' => undef, '_spec' => undef, }, $class; my @dirs = ( ac_path('datadir', 'PACKAGE') ."/defaults", ac_path('sysconfdir', 'PACKAGE') . "/config", tilde_expand( "~/.lire/config" ) ); foreach my $dir ( @dirs ) { next unless -d $dir; $self->add_config_path( $dir ); } my $cfg_file = tilde_expand( "~/.lire/config.xml" ); $self->add_config_file( $cfg_file ) if -f $cfg_file; return $self; } =pod =head2 config_spec() Returns the configuration specification used by the current configuration. =cut sub config_spec { my $self = $_[0]; croak( "config_spec() called while configuration wasn't initialized" ) unless $self->{'_spec'}; return $self->{'_spec'}; } =pod =head2 config_spec_path() Returns a list of directories which will be searched for configuration specification file. By default, configuration specifications are only looked for in F<<datadir>/lire/config-spec>. =cut sub config_spec_path { return @{$_[0]->{'_config_spec_dirs'}}; } =pod =head2 add_config_spec_path_dir( $dir ) This method adds a directory to list of directories that will is used to search for configuration specification files. =cut sub add_config_spec_path_dir { my ( $self, $dir ) = @_; croak "missing 'dir' argument" unless $dir; unshift @{$self->{'_config_spec_dirs'}}, $dir; delete $self->{'_spec'}; return; } =pod =head2 del_config_spec_path_dir( $dir ) This method removes a directory from the list of directories that is used to search for configuration specification files. =cut sub del_config_spec_path_dir { my ( $self, $dir ) = @_; croak "missing 'dir' argument" unless $dir; @{$self->{'_config_spec_dirs'}} = grep { $_ ne $dir } $self->config_spec_path(); delete $self->{'_spec'}; return; } =pod =head2 config_files() Returns the list of configuration files that will be used for this configuration. =cut sub config_files { my ( $self, $dir ) = @_; return @{$self->{'_config_files'}} } sub _find_config_files { my $self = shift; my @files; foreach(@_) { if(-d) { opendir DIR, $_ or croak directory_not_readable( $_ ); my @ents = grep { !/^\./ } readdir DIR; closedir DIR; my $d = $_; push @files, map { "$d/$_" } $self->_find_config_files(@ents); } else { push @files, $_ if !/^[.#]/ && /\.xml$/; } } return @files; } =pod =head2 add_config_path( $path ) Adds configuration files to the list of files that are part of the configuration. Directories will be scanned recursively. =cut sub add_config_path { my ( $self, $path ) = @_; check_param( $path, 'path' ); foreach ( $self->_find_config_files( $path ) ) { $self->add_config_file( $_ ); } return; } =pod =head2 add_config_file( $file ) Adds a configuration file to the list of files that will be parsed to initialize the configuration. =cut sub add_config_file { my ( $self, $file ) = @_; check_param( $file, 'file' ); push @{$self->{'_config_files'}}, $file; $self->_load_config_file( $file ) if $self->{'_spec'}; return; } =pod =head2 del_config_file( $file ) Removes a configuration file from the list of files that are part of the configuration. =cut sub del_config_file { my ( $self, $file ) = @_; check_param( $file, 'file' ); @{$self->{'_config_files'}} = grep { $_ ne $file } $self->config_files(); delete $self->{'_parsed_config'}{$file}; return; } =pod =head2 get_config_file($file) Get a parsed configuration file object from the list of files. =cut sub get_config_file { my ( $self, $file ) = @_; check_param( $file, 'file' ); croak("file '$file' is not a known configuration file") unless exists $self->{'_parsed_config'}{$file}; return $self->{'_parsed_config'}{$file}; } =pod =head2 init() This method loads and parses the configuration files. It should be called prior to using the get() method to obtain configuration data. This method will throw an exception in case there is an invalid parameter in the configuration. =cut sub init { my $self = $_[0]; return if $self->{'_spec'}; $self->_load_spec(); $self->_load_config_files(); return; } =pod =head2 get( $varname ) Returns the configuration value for the $varname configuration variable. init() should have been called to load the configuration data before using this method. It will croak() otherwise. If the $varname is unknown, an exception will also be thrown. =cut sub get { return shift->get_var( @_ )->as_value(); } =pod =head2 get_var( $varname ) Returns the configuration value for the $varname configuration variable as the configuration object. init() should have been called to load the configuration data before using this method. It will croak() otherwise. If the $varname is unknown, an exception will also be thrown. =cut sub get_var { my ( $self, $name ) = @_; croak( "Configuration queried without initialization" ) unless $self->{'_spec'}; croak "No such configuration variable: $name" unless $self->{'_spec'}->has_component($name); foreach my $file ( reverse $self->config_files() ) { my $cfg = $self->{'_parsed_config'}{$file}->global(); return $cfg->get( $name ) if ( $cfg && $cfg->is_set( $name ) ); } return $self->{'_defaults'}->get( $name ); } sub _load_spec { my $self = $_[0]; my $parser = new Lire::Config::SpecParser; foreach my $dir ( $self->config_spec_path() ) { $parser->merge_specifications_dir( $dir ); } $self->{'_spec'} = $parser->configspec(); $self->{'_defaults'} = $self->{'_spec'}->instance(); return; } sub _load_config_files { my $self = $_[0]; $self->{'_parsed_config'} = {}; foreach my $file ( $self->config_files() ) { $self->_load_config_file( $file ); } return; } sub _load_config_file { my ( $self, $file ) = @_; my $parser = new Lire::Config::Parser( 'spec' => $self->{'_spec'} ); $self->{'_parsed_config'}{$file} = $parser->load_config_file( $file ); return; } # keep perl happy 1; __END__ =pod =head1 DEBUGGING One can call this module direct from the commandline, e.g. for debugging purposes, by doing something like: perl -e 'use lib "/path/to/your/share/perl5"; use Lire::Config; \ use Lire::Program; print Lire::Config->get( "lr_mail_from" ), "\n"' or perl -e 'use Lire::Config; use Lire::Program; \ $a = Lire::Config->get( lr_converters_init_path ); print "@$a\n"; ' . =head1 SEE ALSO Lire::Config::TypeSpec(3pm), Lire::Config::Value(3pm) =head1 AUTHORS Wessel Dankers <wsl@logreport.org> Francis J. Lacoste <flacoste@logreport.org> Joost van Baal <joostvb@logreport.org> =head1 VERSION $Id: Config.pm,v 1.47 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ���������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/DlfStream.pm����������������������������������������������������������������0000644�0001750�0001750�00000016765�10460672574�014051� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::DlfStream; use strict; use Lire::DlfSchema; use Lire::DlfQuery; use Lire::I18N qw/ensure_utf8 /; use Lire::Utils qw/ check_param check_object_param /; use Carp; =pod =head1 NAME Lire::DlfStream - Interface to DLF data stream =head1 SYNOPSIS use Lire::DlfStore; my $store = Lire::DlfStore->open( "mystore" ); my $dlf_stream = $store->open_dlf_stream( "www", "r" ); print "Data begins on ", scalar localtime $dlf_stream->start_time(), "\n"; print "Data ends on ", scalar localtime $dlf_stream->end_time(), "\n"; while ( my $dlf = $dlf_stream->read_dlf() ) { ... } =head1 DESCRIPTION This object encapsulates DLF stream. =cut #------------------------------------------------------------------------ # Constructor new( $store, $name, $mode ) # # Used by Lire::DlfStore sub new { my ( $pkg, $store, $name, $mode, $sort_spec ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); check_param( $mode, 'mode', sub { $mode eq 'r' || $mode eq 'w' }, "'mode' should be one of 'r' or 'w'" ); croak "only 'r' mode stream can use a sort_spec" if $mode ne 'r' && $sort_spec; my $self = bless { '_store' => $store, '_name' => $name, '_mode' => $mode, '_sort_spec' => $sort_spec, '_schema' => Lire::DlfSchema::load_schema( $name ), }, $pkg; if ( ! $self->{'_store'}->has_dlf_stream( $self->{'_name'} ) ) { $self->{'_schema'}->create_sql_schema( $self->{'_store'} ); } elsif ( $self->{'_schema'}->needs_sql_schema_migration($self->{'_store'})) { $self->{'_schema'}->migrate_sql_schema( $self->{'_store'} ); } if ( $mode eq "w" ) { my $sql = $self->{'_schema'}->sql_insert_query(); $self->{'_sth'} = $self->{'_store'}->_dbh()->prepare_cached( $sql ); if ( $self->{'_schema'}->isa( 'Lire::DerivedSchema' ) ) { $sql = $self->{'_schema'}->sql_link_insert_query(); $self->{'_link_sth'} = $self->{'_store'}->_dbh()->prepare_cached( $sql ); } } else { $self->{'_dlf_reader'} = $self->{'_schema'}->dlf_query( $sort_spec )->execute( $store ); } return $self; } =pod =head2 name Returns the schema's name of the DlfStream. =cut sub name { $_[0]{'_name'}; } =pod =head2 mode() Returns the mode in which the DlfStream was opened. =cut sub mode { $_[0]{'_mode'}; } =pod =head2 sort_spec() Returns the sort specification that is set on the stream. =cut sub sort_spec { $_[0]{'_sort_spec'}; } =pod =head2 close() This method should be called when the Lire::DlfStream isn't needed anymore, otherwise the same DlfStream cannot be opened until then. =cut sub close { my $self = $_[0]; if ( $self->{'_sth'} ) { $self->{'_sth'}->finish(); delete $self->{'_sth'}; } elsif ( $self->{'_dlf_reader'} ) { $self->{'_dlf_reader'}->dlf_query()->release(); delete $self->{'_dlf_reader'}; } } sub DESTROY { $_[0]->close(); } =pod =head2 nrecords() Returs the number of DLF records in the stream. =cut sub nrecords { my $self = $_[0]; return $self->_get_stat( "nrecords", "count()"); } =pod =head2 start_time() Returns the timestamp of the oldest DLF record in the stream in seconds since the epoch. =cut sub start_time { my $self = $_[0]; my $field = $self->{'_schema'}->timestamp_field()->name(); return $self->_get_stat( 'start_time', sprintf( "min(%s)", $field ) ); } =pod =head2 end_time() Returns the timestamp of the newest DLF record in the stream in seconds since the epoch. =cut sub end_time { my $self = $_[0]; my $field = $self->{'_schema'}->timestamp_field()->name(); return $self->_get_stat( 'end_time', sprintf( "max(%s)", $field ) ); } sub _get_stat { my ( $self, $name, $expr ) = @_; my $query = new Lire::DlfQuery( $self->{'_name'} ); $query->add_aggr_field( $name, $expr ); my $result = $query->execute( $self->{'_store'} ); my $stat = $result->next_row()->{$name}; $query->release(); return $stat; } =pod =head2 read_dlf() Returns an hash reference containing the next DLF record in the stream. It returns undef once the end of the stream is reached. This method will throw an exception if the DlfStream isn't open in 'r' mode or if there is an error reading the DLF record. =cut sub read_dlf { my $self = $_[0]; croak "read_dlf() can't be called on a DlfStream open in 'w' mode" if $self->{'_mode'} ne 'r'; return $self->{'_dlf_reader'}->next_row(); } =pod =head2 read_dlf_aref() Returns the next DLF record in the stream as an array reference. The fields are in the order specified by the schema. This method will throw an exception if the DlfStream isn't open in 'r' mode or if there is an error reading the DLF record. =cut sub read_dlf_aref { my $self = $_[0]; croak "read_dlf_aref() can't be called on a DlfStream open in 'w' mode" if $self->{'_mode'} ne 'r'; return $self->{'_dlf_reader'}->next_row_aref(); } =pod =head2 write_dlf( $dlf, [ $link_ids ] ) Writes the fields contained in the hash ref $dlf to the DLF stream. This method will throw an exception if there is an error writing the DLF record or if the stream isn't opened in 'w' mode. The $link_ids parameter is used when the stream's schema is a Lire::DerivedSchema. It should be an array reference containing the DLF ids of the records which are linked to this record. =cut sub write_dlf { my ( $self, $dlf, $link_ids ) = @_; croak "write_dlf() can't be called on a DlfStream open in 'r' mode" if $self->{'_mode'} ne 'w'; croak "missing DLF hash reference" unless defined $dlf; croak "DLF record isn't an hash reference: $dlf" unless ref $dlf eq 'HASH'; croak "'dlf_id' field must be set when using write_dlf() on an extended schema" if ( $self->{'_schema'}->isa( 'Lire::ExtendedSchema' ) && ! defined $dlf->{'dlf_id'} ); croak "'link_ids' parameter should be an ARRAY reference, not '$link_ids'" if ( $self->{'_schema'}->isa( 'Lire::DerivedSchema' ) && defined $link_ids && ref( $link_ids ) ne 'ARRAY' ); my @values = (); foreach my $f ( map { $_->name() } $self->{'_schema'}->_sql_fields() ) { my $v = $dlf->{$f}; # replace control chars with ? $v =~ tr/\000-\037/?/ if defined $v; push @values, ensure_utf8( $v ); } $self->{'_sth'}->execute( @values); $self->_write_derived_links( $link_ids ) if $self->{'_schema'}->isa( 'Lire::DerivedSchema' ); return; } sub _write_derived_links { my ( $self, $link_ids ) = @_; $link_ids ||= []; return unless @$link_ids; my $src_id = $self->{'_store'}->_dbh()->selectrow_arrayref( 'SELECT last_insert_rowid()' ); foreach my $link_id ( @$link_ids ) { $self->{'_link_sth'}->execute( $src_id->[0], $link_id); } } =pod =head2 clean( [ $time ] ) This method will remove all DLF records older than $time. It $time is omitted, all Dlf records will be removed. =cut sub clean { my ( $self, $time ) = @_; croak "clean() can't be called on a DlfStream open in 'r' mode" if $self->{'_mode'} ne 'w'; my $sql = $self->{'_schema'}->sql_clean_query( defined $time ); if ( defined $time ) { $self->{'_store'}->_dbh()->do( $sql, {}, $time ); } else { $self->{'_store'}->_dbh()->do( $sql ); } return; } 1; �����������lire-2.1.1/all/lib/Lire/ReportSpec.pm���������������������������������������������������������������0000644�0001750�0001750�00000023554�10460673256�014246� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ReportSpec; use strict; use base qw/ Lire::XMLSpecContainer /; use Carp; use Lire::Config; use Lire::DataTypes qw/ check_xml_name /; use Lire::XMLSpecContainer; use Lire::Report::Subreport; use Lire::Report::TableInfo; use Lire::PluginManager; use Lire::Utils qw/ check_param check_object_param /; =pod =head1 NAME Lire::ReportSpec - API to the XML report specifications. =head1 SYNOPSIS use Lire::ReportSpec; =head1 DESCRIPTION =head1 META INFORMATION METHODS =head2 list_specs( $superservice ) Returns an array reference containing all the report specification type available for the $superservice superservice. =head2 has_spec( $superservice, $type ) Returns true if there is a $type specification available for the $superservice. =cut ######################################################################## # Lire::XMLSpecContainer METHODS ######################################################################## sub root_element { my ( $self ) = @_; return "report-spec"; } sub spec_path { return Lire::Config->get( 'lr_reports_path' ); } sub print_children { my ( $self, $fh, $indent ) = @_; my $pfx = ' ' x $indent; if ( defined $self->{'filter_spec'} ) { print $fh "$pfx<lire:filter-spec>\n"; $self->{'filter_spec'}->print( $fh, $indent + 1); print $fh "\n$pfx</lire:filter-spec>\n\n"; } if ( defined $self->{'_chart_configs'} || $self->{'charttype'} ) { print $fh "$pfx<lire:chart-configs>\n"; foreach my $cfg ( @{$self->chart_configs()} ) { $cfg->save_xml( $fh, $indent + 1, 'lrcml:' ); } print $fh "$pfx</lire:chart-configs>\n\n"; } print $fh "$pfx<lire:report-calc-spec>\n"; $self->{'calc_spec'}->print( $fh, $indent + 1 ); print $fh "$pfx</lire:report-calc-spec>\n"; } sub new_from_config { my ( $self, $value ) = @_; my $spec = $self->SUPER::new_from_config( $value ); $spec->subreport_id( $value->get( 'id' )->as_value() ); $spec->{'_chart_configs'} = []; foreach my $cfg ( @{$value->get( 'charts' )->as_value()} ) { $spec->add_chart_config( $cfg ); } return $spec; } =pod =head1 OBJECT METHODS =head2 subreport_id( [ $new_subreport_id ] ) Returns (and optionnally change) the id that will be associated to the Subreport that will be generated by this specification. =cut sub subreport_id { my ( $self, $id ) = @_; if ( defined $id ) { check_param( $id, 'subreport_id', \&check_xml_name ); $self->{'_subreport_id'} = $id; } return $self->{'_subreport_id'}; } sub charttype2chart_config { my ( $charttype, $id, $table_info ) = @_; check_param( $charttype, 'charttype', qr/^(histogram|pie|lines|bars)$/ ); check_object_param( $table_info, 'table_info', 'Lire::Report::TableInfo' ); my $cfg = new Lire::Report::ChartConfig(); $cfg->basename( $id ); my ( $name_col, $value_col ); foreach my $col ( $table_info->column_infos() ) { $name_col = $col->name() if ! $name_col && $col->class() eq 'categorical'; $value_col = $col->name() if ! $value_col && $col->class() eq 'numerical'; last if $name_col && $value_col; } $cfg->get( 'case_var' )->set( $name_col ); if ( $charttype eq 'pie' ) { $cfg->type( Lire::PluginManager->get_plugin( 'chart_type', 'pie' ) ); $cfg->type_properties()->get( 'values' )->set( $value_col ); } elsif ( $charttype eq 'lines' ) { $cfg->type( Lire::PluginManager->get_plugin( 'chart_type', 'lines' ) ); $cfg->type_properties()->get( 'y' )->set( $value_col ); } else { $cfg->type( Lire::PluginManager->get_plugin( 'chart_type', 'vbars' ) ); $cfg->type_properties()->get( 'y' )->set( $value_col ); } return $cfg; } sub default_chart_config { my $self = $_[0]; return undef unless $self->{'charttype'}; return charttype2chart_config( $self->{'charttype'}, $self->subreport_id(), $self->create_table_info() ); } =pod =head2 chart_configs() Returns an array reference containing the Lire::Report::ChartConfig objects that specifies the charts that should be generated when the Lire::Report::Subrpeport object specified by this object will be formatted. =cut sub chart_configs { my $self = $_[0]; if ( $self->{'_chart_configs'} ) { return $self->{'_chart_configs'}; } else { my $cfg = $self->default_chart_config(); return $cfg ? [ $cfg ] : []; } } =pod =head2 add_chart_config( $chart_config ) Adds a Lire::Report::ChartConfig object that should be added to the Lire::Report::Subreport object that is specified by this object. =cut sub add_chart_config { my ( $self, $chart_config ) = @_; check_object_param( $chart_config, 'chart_config', 'Lire::Report::ChartConfig' ); $self->{'_chart_configs'} ||= []; push @{$self->{'_chart_configs'}}, $chart_config; return; } sub charttype { my ( $self, $chart ) = @_; if ( @_ == 2 ) { if ( $chart) { check_param( $chart, 'chart' ); $self->{'charttype'} = $chart; } else { delete $self->{'charttype'}; } } return $self->{'charttype'}; } =pod =head2 filter_spec( [ $new_filter_spec ] ) Returns (and optionally changes) the Lire::FilterExpr that should be applied to create the Lire::Report::Subreport specified by this object. This will be undef if no filtering should be applied. =cut sub filter_spec { my ( $self, $filter_spec ) = @_; if ( @_ == 2 ) { if ( defined $filter_spec ) { check_object_param( $filter_spec, 'filter_spec', 'Lire::FilterExpr' ); $self->{'filter_spec'} = $filter_spec; } else { delete $self->{'filter_spec'}; } } return $self->{'filter_spec'}; } =pod =head2 calc_spec( [ $new_aggregator ] ) Returns (and optionally changes) the Lire::Aggregator that should be used to create the Lire::Report::Subreport specified by this object. =cut sub calc_spec { my ( $self, $calc_spec ) = @_; if ( @_ == 2 ) { check_object_param( $calc_spec, 'calc_spec', 'Lire::Aggregator' ); $self->{'calc_spec'} = $calc_spec; } return $self->{'calc_spec'}; } =pod =head2 mark_missing( $reason ) Mark that the report that should be generated by this report specification should be marked as missing. The $reason parameter gives the reason why the subreport will be missing. =cut sub mark_missing { my ( $self, $reason ) = @_; $self->{'missing'} = $reason; return; } =pod =head2 is_missing() Returns true if the subreport generated by this report specification should be marked missing. =cut sub is_missing { return defined $_[0]{'missing'}; } =pod =head2 set_store( $store ) Sets the DLF store upon which this ReportSpec will be generated when create_subreport() will be called. =cut sub set_store { my ( $self, $store ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); croak "store doesn't contain a '", $self->schema()->id(), "' DLF stream " unless $store->has_dlf_stream( $self->schema()->id() ); $self->calc_spec()->_set_store( $store ); return; } =pod =head2 create_subreport() Creates a Lire::Report::Subreport object based on this report specification. This will be a missing subreport if the mark_missing() method was called. Called by Lire::ReportSection::create_report_section(). =cut sub create_subreport { my $self = $_[0]; if ( $self->{'missing'} ) { my $sub = new_missing Lire::Report::Subreport( $self->superservice(), $self->id(), $self->{'missing'} ); $sub->id( $self->subreport_id() ); $sub->schemas( @{$self->schemas()} ); return $sub; } my $subreport = new Lire::Report::Subreport( $self->superservice(), $self->id() ); $subreport->id( $self->subreport_id() ); $subreport->schemas( @{$self->schemas()} ); $subreport->title( $self->expanded_display_title() ); foreach my $cfg ( @{$self->chart_configs()} ) { $subreport->add_chart_config( $cfg->clone() ); } $subreport->description( $self->expanded_display_description() ); $subreport->table_info( $self->create_table_info() ); $self->calc_spec()->create_entries( $subreport ); $subreport->finalize(); return $subreport; } =pod =head2 create_table_info() Returns a Lire::Report::TableInfo object that describes the table generated by subreport of this type. =cut sub create_table_info { my $self = $_[0]; my $info = new Lire::Report::TableInfo(); $self->calc_spec()->create_group_info( $info ); $info->compute_group_layout(); return $info; } 1; __END__ =pod =head1 SEE ALSO Lire::FilterSpec(3pm), Lire::ReportConfig(3pm), Lire::ReportSection(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: ReportSpec.pm,v 1.59 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ����������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Error.pm��������������������������������������������������������������������0000644�0001750�0001750�00000010576�10460673255�013250� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Error; use strict; use base qw/ Exporter /; use vars qw/ @EXPORT_OK /; BEGIN { @EXPORT_OK = qw/ an_error_occured directory_already_exists file_empty directory_not_readable file_not_readable file_not_writable invalid_option invalid_superservice missing_command missing_argument missing_argument_usage too_many_arguments unknown_command_usage /; }; use Locale::TextDomain 'lire'; use Lire::Utils qw/ check_param /; =pod =head1 NAME Lire::Error - standard error messages library =head1 SYNOPSIS use Lire::Error qw/ file_not_readable directory_already_exists /; open my $fh, '/tmp/mikwuk' or die file_not_readable( 'mikwuk' ); croak directory_already_exists( '/tmp/tempdir/wawadir' ) if ( -d '/tmp/tempdir/wawadir' ); =head1 DESCRIPTION This modules implements an API to obtain all the standard error messages that are found across the Lire scripts, utilities or modules. Most of them are translated appropriately. =cut sub an_error_occured { my $error = $_[0]; check_param( $error, 'error' ); return __x( "An error occured: {error}", 'error' => $error ); } sub file_empty { my $file = $_[0]; check_param( $file, 'file' ); return __x( "file '{file}' is empty", 'file' => $file ); } sub directory_not_readable { my $directory = $_[0]; check_param( $directory, 'directory' ); return __x( "could not open '{file}' for reading: {error}", 'file' => $directory, 'error' => $! ); } sub file_not_readable { my $file = $_[0]; check_param( $file, 'file' ); return __x( "could not open '{file}' for reading: {error}", 'file' => $file, 'error' => $! ); } sub file_not_writable { my $file = $_[0]; check_param( $file, 'file' ); return __x( "could not open '{file}' for writing: {error}", 'file' => $file, 'error' => $! ); } sub invalid_option { my $option = $_[0]; check_param( $option, 'option' ); return __x( "invalid option: '{option}'", 'option' => $option ); } sub invalid_superservice { my $super = $_[0]; check_param( $super, 'superservice' ); return __x( "invalid superservice: '{superservice}'", 'superservice' => $super ); } sub missing_command { my ( $command, $make ) = @_; check_param( $command, 'command' ); return ( defined $make ? __x( "missing {make} '{command}' command", 'make' => $make, 'command' => $command ) : __x( "missing '{command}' command", 'command' => $command ) ); } sub missing_argument { my $argument = $_[0]; check_param( $argument, 'argument' ); return __x( "missing '{argument}' argument", 'argument' => $argument ); } sub missing_argument_usage { my $argument = $_[0]; check_param( $argument, 'argument' ); return __x( "Missing '{argument}' argument.\n", 'argument' => $argument ); } sub directory_already_exists { my $directory = $_[0]; check_param( $directory, 'directory' ); return __x( "directory '{directory}' already exists", 'directory' => $directory ); } sub too_many_arguments { return __( "too many arguments" ); } sub unknown_command_usage { my $command = $_[0]; check_param( $command, 'command' ); return __x( "Unknown command: '{command}'.\n", 'command' => $command ); } # keep perl happy 1; __END__ =pod =head1 AUTHOR Wolfgang Sourdeau <wolfgang@logreport.org> =head1 VERSION $Id: Error.pm,v 1.8 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ����������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/DlfQuery.pm�����������������������������������������������������������������0000644�0001750�0001750�00000054047�10460673254�013712� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::DlfQuery; use strict; use Carp; use Lire::DataTypes qw/ check_xml_name check_int /; use Lire::DlfSchema; use Lire::DlfResult; use Lire::Utils qw/ sql_quote_name check_param check_object_param /; =pod =head1 NAME Lire::DlfQuery - Interface to specialized SQL wrappers used internally by the Lire API. =head1 SYNOPSIS use Lire::DlfQuery; =head1 DESCRIPTION =head2 new( $stream_name ) This is the constructor method for the Lire::DlfQuery class. It takes a dlf stream name and a Lire::DlfStore object as parameters. Lire::DlfStore is expected to contain the specified stream. Both parameters are mandatory. This method returns an instance of Lire::DlfQuery. =cut sub new { my ( $class, $stream_name ) = @_; check_param( $stream_name, 'stream_name' ); croak "there is no schema '$stream_name'" unless Lire::DlfSchema->has_schema( $stream_name ); my $self = bless {}, $class; $self->{'_stream_name'} = $stream_name; $self->{'_fields'} = []; $self->{'_field_refs'} = {}; $self->{'_order_by'} = undef; $self->{'_limit'} = 0; $self->{'_filter_clause'} = undef; $self->{'_filter_params'} = []; $self->{'_parent'} = undef; $self->{'_nested_queries'} = []; $self->{'_joined_streams'} = []; return $self; } =pod =head2 stream_name() Returns the DLF stream's name upon which this DlfQuery is defined. =cut sub stream_name { return $_[0]{'_stream_name'}; } sub schema { return Lire::DlfSchema::load_schema( $_[0]->{'_stream_name'} ); } =pod =head2 join_stream( $stream_name ) This method can be used to add an ExtendedSchema stream which will be joined in the query. =cut sub join_stream { my ( $self, $stream_name ) = @_; check_param( $stream_name, 'stream_name' ); croak "there is no schema: '$stream_name'" unless Lire::DlfSchema->has_schema( $stream_name ); croak "'$stream_name' is already joined" if grep { $_ eq $stream_name } @{ $self->joined_streams() }; croak "can only join streams on root query" if defined $self->{'_parent'}; my $joined_schema = Lire::DlfSchema::load_schema( $stream_name ); croak "cannot join '$stream_name' with '$self->{'_stream_name'}'" unless $self->schema()->can_join_schema( $joined_schema ); push @{$self->{'_joined_streams'}}, $stream_name; return; } =pod =head2 joined_streams() Returns as an array reference all the streams that are part of the query. =cut sub joined_streams { my $self = $_[0]; return [ $self->{'_stream_name'}, @{$self->{'_joined_streams'}} ]; } =pod =head2 release() Nested DlfQuery introduce a circular reference between the children and the parent. Call release() on the top-level DlfQuery to remove the circular when the DlfQuery object isn't needed anymore, so that perl can garbage collect the objects. =cut sub release { my $self = $_[0]; delete $self->{'_parent'}; foreach my $query ( @{ $self->nested_queries() } ) { $query->release(); } return; } sub _schema_has_field { my ( $self, $field_name ) = @_; foreach my $schema ( @{$self->joined_streams()} ) { return 1 if Lire::DlfSchema::load_schema( $schema )->has_field( $field_name ); } return 0; } sub _field_by_name { return $_[0]->{'_field_refs'}{$_[1]}; } =pod =head2 create_nested_query() This method will create and return an instance of Lire::DlfQuery nested within the current query. The returned query will be modified later with regular methods. =cut sub create_nested_query { my $self = $_[0]; croak "can't create a nested query on query containing simple fields" if ( @{$self->_fields_of_type( 'simple' ) } ); my $nested = new Lire::DlfQuery( $self->{'_stream_name'}, $self->{'_store' } ); $nested->{'_parent'} = $self; push @{$self->{'_nested_queries'}}, $nested; return $nested; } sub _root_query { my $self = $_[0]; my $root = $self; while ( defined $root->{'_parent'} ) { $root = $root->{'_parent'}; } return $root; } =pod =head2 nested_queries() This method returns a reference to an array containing all the nested queries of the current query. =cut sub nested_queries { return [ @{$_[0]{'_nested_queries'}} ]; } sub _find_field_def { my ( $self, $field_name ) = @_; my $queries = $self->_query_subtree_from_root(); foreach my $q (@$queries) { my $field = $q->_field_by_name( $field_name ); return $field if defined $field; } return undef; } =pod =head2 has_field( $field_name ) Returns true if there is a field $field_name defined in the query. =cut sub has_field { my ( $self, $field_name ) = @_; return defined $self->_find_field_def( $field_name ); } =pod =head2 field_def( $field_name ) Returns the SQL expression that is associated with the field $field_name in the query. This method will throw an exception if there is no field $field_name defined in the query. =cut sub field_def { my ( $self, $field_name ) = @_; my $field = $self->_find_field_def( $field_name ); croak "no field '$field_name' defined in the query" unless defined $field; return $field->{'field'}; } sub _fields_of_type { my ( $self, $type ) = @_; croak "type should be 'simple', 'group', 'aggr' or 'group+aggr': '$type'" unless ( $type eq 'simple' || $type eq 'group' || $type eq 'aggr' || $type eq 'group+aggr'); my @fields = (); foreach my $f ( @{ $self->{'_fields'} } ) { if ( $type eq 'group+aggr') { next unless $f->{'type'} eq 'group' || $f->{'type'} eq 'aggr'; } else { next unless $f->{'type'} eq $type; } push @fields, $f; } return \@fields; } sub _query_subtree_from_root { my $self = $_[0]; my @subtree = (); my $current = $self; while (defined $current) { unshift @subtree, $current; $current = $current->{'_parent'}; } $self->_nested_queries_subtree ( \@subtree ); return \@subtree; } sub _nested_queries_subtree { my ( $self, $subtree ) = @_; foreach my $child ( @{$self->{'_nested_queries'}} ) { push @$subtree, $child; $child->_nested_queries_subtree( $subtree ); } return; } sub _field_name { my $field = $_[0]; return (defined $field->{'alias'}) ? $field->{'alias'} : $field->{'field'}; } =pod =head2 fields() Returns the name of the fields defined as simple fields in an array reference. These are fields added through the add_field() method. =cut sub fields { my $self = $_[0]; return [ map { _field_name($_) } @{$self->_fields_of_type( 'simple' )} ]; } =pod =head2 group_fields() Returns the name of the fields defined as group fields in an array reference. These are fields added through the add_group_field() method. =cut sub group_fields { my $self = $_[0]; my @fields = @{$self->_traverse_from_parent( sub { @{$_[0]->_fields_of_type( 'group' )} } ) }; push @fields, @{$self->_fields_of_type( 'group' )}; return [ map { _field_name($_) } @fields ]; } =pod =head2 aggr_fields() Returns the name of the fields defined as aggregate fields in an array reference. These are fields added through the add_aggr_field() method. =cut sub aggr_fields { my $self = $_[0]; my $queries = [ $self ]; $self->_nested_queries_subtree( $queries ); my @fields = (); foreach my $q (@$queries) { push @fields, @{$q->_fields_of_type( 'aggr' )}; } return [ map { _field_name($_) } @fields ]; } sub _add_field { my ( $self, $field, $type, $alias ) = @_; check_param( $field, 'field' ); check_param( $type, 'type', qr/^(simple|group|aggr)$/, "type should be 'simple', 'group', 'aggr'" ); if (defined $alias) { croak "field name should contain only alphanumeric characters: '$alias'" unless ( check_xml_name ($alias) ); croak "'$alias' is already defined in the query" if ( $self->has_field( $alias ) ); } else { croak "field name should contain only alphanumeric characters: '$field'" unless ( check_xml_name ($field) ); croak "no field '$field' in '$self->{'_stream_name'}' schema" unless ( $self->_schema_has_field( $field ) || $type ne 'simple' ); croak "'$field' is already defined in the query" if ( $self->has_field( $field ) ); } my $field_ref = { 'field' => $field, 'alias' => $alias, 'type' => $type }; push @{$self->{'_fields'}}, $field_ref; $self->{'_field_refs'}{(defined $alias) ? $alias : $field} = $field_ref; return; } =pod =head2 add_field( $field_name, $expr ) Add a simple field to the current query. The first parameter will be the field name. The second represents an expression that will then be aliased with the specified field name. Only the field name is mandatory. Certain restrictions apply: simple fields cannot be added to queries containing either subqueries or group fields. =cut sub add_field { my ( $self, $field_name, $expr ) = @_; croak "calls to add_field() and add_group_field() can't be mixed " . "on the same Lire::DlfQuery" if ( @{ $self->_fields_of_type( 'group' ) } ); croak "can't add simple field to a query containing nested queries" if ( @{ $self->nested_queries() } ); if (defined $expr) { $self->_add_field( $expr, 'simple', $field_name ); } else { $self->_add_field( $field_name, 'simple' ); } return; } =pod =head2 add_aggr_field( $field_name, $aggregate ) Add a group field to the current query. The first parameter will be the field name. The second represents the aggregate expression that will then be aliased with the specified field name. Both parameters are mandatory. Aggregate field can only be added to queries which contain group fields. =cut sub add_aggr_field { my ( $self, $field_name, $aggregate ) = @_; check_param ( $aggregate, 'aggregate' ); $self->_add_field( $aggregate, 'aggr', $field_name ); return; } =pod =head2 add_group_field( $field_name, $expr ) Add a group field to the current query. The first parameter will be the field name. The second represents an expression that will then be aliased with the specified field name. Only the field name is mandatory. Certain restrictions apply: group fields cannot be added to queries containing simple fields. =cut sub add_group_field { my ( $self, $field_name, $expr ) = @_; croak "calls to add_field() and add_group_field() can't be mixed " . "on the same Lire::DlfQuery" if ( @{ $self->_fields_of_type( 'simple' ) } ); if (defined $expr) { $self->_add_field( $expr, 'group', $field_name ); } else { $self->_add_field( $field_name, 'group' ); } return; } =pod =head2 set_order_by_clause( $clause ) Sets the order clause of the query, that is, what will appear in the "ORDER BY" clause of the SQL statement. =cut sub set_order_by_clause { my ( $self, $clause ) = @_; $self->{'_sort_spec'} = undef; $self->{'_order_by'} = ( defined $clause && $clause ne '' ) ? $clause : undef; return; } =pod =head2 order_by_clause() Returns the current ORDER BY clause or undef when none was set. =cut sub order_by_clause { return $_[0]{'_order_by'}; } sub _is_valid_sort_field { my ( $self, $field ) = @_; return ( grep { $_ eq $field } @{$self->aggr_fields()}, @{$self->group_fields()}, @{$self->fields()} ) > 0; } =pod =head2 set_sort_spec( $spec ) =cut sub set_sort_spec { my ( $self, $spec ) = @_; if ( !defined $spec || $spec eq '' ) { $self->{'_sort_spec'} = undef; $self->{'_order_by'} = undef; return; } my @sfields = (); foreach my $field_spec ( split /\s+/, $spec ) { my $field = $field_spec; my $is_desc = 0; if ( substr( $field, 0, 1) eq '-' ) { $field = substr( $field, 1 ); $is_desc = 1; } croak "field '$field' unavailable for sorting" unless ( $self->_is_valid_sort_field( $field ) ); push @sfields, $is_desc ? sql_quote_name( $field ) . " DESC" : sql_quote_name( $field ); } $self->{'_sort_spec'} = $spec; $self->{'_order_by'} = join( ", ", @sfields ); return; } =pod =head2 sort_spec() Returns the sort specification that was set using set_sort_spec(). If no sort specification was set (or it was set using the set_order_by_clause() method), this will be undef. =cut sub sort_spec { return $_[0]->{'_sort_spec'}; } =pod =head2 set_limit() Sets the limit clause of the query, that is, what will appear in the "LIMIT" clause of the SQL statement. This method will also have an impact on the internal handling of the query. =cut sub set_limit { my ( $self, $limit ) = @_; croak "'limit' parameter should be an integer: '$limit'" unless ( !defined $limit || check_int( $limit ) ); $self->{'_limit'} = (defined $limit) ? $limit : 0; return; } =pod =head2 limit() Returns the maximum number of records that should be returned by the query. When no limit was set, it returns 0. =cut sub limit { return $_[0]{'_limit'}; } =pod =head2 set_filter_clause( $clause, @params ) Sets the filter clause of the query, the filter clause being the SQL restrictions on the results that will be return by the query, i.e. what will appear in the "WHERE" clause of the SQL statement. It is compatible with the DBI handling of placeholders ('?'). Of course, the amount of placeholders has to be the same of the amount of values and variables that are passed in @params. Only the clause parameter is mandatory, the number of elements in @params being dependent on the amount of placeholders specified therein. =cut sub set_filter_clause { my ( $self, $clause, @params ) = @_; $clause ||= ''; my $nbr_ph = $clause =~ tr/?/?/; my $nparams = @params; croak "invalid number of parameters: filter clause contains $nbr_ph placeholders while $nparams values provided" if ($nbr_ph != $nparams); $self->{'_filter_clause'} = ($clause ne '') ? $clause : undef; $self->{'_filter_params'} = \@params; return; } =pod =head2 filter_clause() Returns the current WHERE clause or undef when none was set. =cut sub filter_clause { return $_[0]{'_filter_clause'}; } sub _traverse_from_parent { my ( $self, $sub ) = @_; my @elmnts = (); my $cur = $self; while ( defined $cur->{'_parent'} ) { unshift @elmnts, $sub->( $cur->{'_parent'} ); $cur = $cur->{'_parent'}; } return \@elmnts; } sub _sql_select_fields { my ( $self, $is_summary ) = @_; my @fields; if ( $is_summary ) { push @fields, @{$self->_fields_of_type( 'aggr' ) }; } elsif ( @{$self->_fields_of_type( 'simple' ) } ) { push @fields, @{$self->_fields_of_type( 'simple' ) }; } else { push @fields, @{$self->_fields_of_type( 'group+aggr' ) }; } foreach my $child ( @{$self->{'_nested_queries'}} ) { push @fields, @{$child->_sql_select_fields( 1 )}; } return \@fields; } sub _sql_select_clause { my ( $self, $is_summary ) = @_; my @fields = @{$self->_traverse_from_parent( sub { @{$_[0]->_fields_of_type( 'group' )} } )}; push @fields, @{$self->_sql_select_fields( $is_summary )}; my @expr = (); foreach my $field ( @fields ) { if ( $field->{'alias'} ) { push @expr, $field->{'field'} . ' AS '. sql_quote_name( $field->{'alias'} ); } else { push @expr, sql_quote_name( $field->{'field'} ); } } return 'SELECT '.join( ",\n ", @expr ); } sub _sql_from_clause { my $self = $_[0]; my $schema = $self->schema(); my @tables = ( $schema->sql_table() ); if ( $schema->isa( 'Lire::ExtendedSchema' ) ) { unshift @tables, $schema->base()->sql_table(); } elsif ( $self->_needs_links_table() ) { push @tables, $schema->sql_table( '', '_links' ); } foreach my $name ( @{$self->{'_joined_streams'}} ) { push @tables, Lire::DlfSchema::load_schema( $name )->sql_table(); } return "FROM " . join( ", ", @tables ); } sub _needs_links_table { my $self = $_[0]; my $schema = $self->schema(); return ( $schema->isa( 'Lire::DerivedSchema' ) && grep { my $joined = Lire::DlfSchema::load_schema( $_ ); return ( ! $joined->isa( 'Lire::ExtendedSchema' ) || $joined->base() ne $schema ) } @{$self->{'_joined_streams'}} ); } sub _sql_where_clause { my $self = $_[0]; my @elmnts = @{$self->_sql_where_join_elements()}; my $filter_collector = sub { defined $_[0]{'_filter_clause'} ? $_[0]{'_filter_clause'} : () }; push @elmnts, @{$self->_traverse_from_parent( $filter_collector )}; push @elmnts, $self->{'_filter_clause'} if ( defined $self->{'_filter_clause'} ); return @elmnts ? "WHERE " . join ( " AND ", @elmnts ) : (); } sub _sql_where_join_elements { my $self = $_[0]; my $schema = $self->schema(); my @elmnts = (); if ( $self->_needs_links_table() ) { push @elmnts, $schema->sql_table() . ".dlf_id = " . $schema->sql_table( '', '_links' ) . ".src_id"; } foreach my $name ( @{ $self->joined_streams() } ) { my $joined = Lire::DlfSchema::load_schema( $name ); if ( $schema->isa( 'Lire::DerivedSchema' ) ) { if ( $joined->isa( 'Lire::ExtendedSchema' ) && $joined->base() eq $schema ) { push( @elmnts, $schema->sql_table() . '.dlf_id = ' . $joined->sql_table() . '.dlf_id' ); } elsif ( ( $joined->isa( 'Lire::ExtendedSchema' ) && $joined->base() ne $schema ) || $joined eq $schema->base() ) { push( @elmnts, $schema->sql_table( '', '_links' ) .'.link_id = ' . $joined->sql_table() . '.dlf_id' ); } } elsif ( $joined->isa( 'Lire::ExtendedSchema' ) ) { push( @elmnts, $joined->base()->sql_table() . '.dlf_id = ' . $joined->sql_table() . '.dlf_id' ); } } return \@elmnts; } sub _sql_group_by_clause { my ( $self, $is_summary ) = @_; return () if $self->{'_parent'} && @{$self->_fields_of_type( 'simple' )}; my @fields = (); if ($is_summary) { my @defs = @{$self->_traverse_from_parent( sub { @{$_[0]->_fields_of_type( 'group' )} } ) }; @fields = map { sql_quote_name( _field_name($_) ) } @defs; } else { @fields = map { sql_quote_name( $_ ) } @{$self->group_fields()}; } return @fields ? "GROUP BY " . join ( ", ", @fields ) : (); } sub _sql_order_by_clause { my ( $self, $is_summary ) = @_; my @elmnts = @{$self->_traverse_from_parent( sub { defined ($_[0]->{'_order_by'}) ? $_[0]->{'_order_by'} : () } ) }; push @elmnts, $self->{'_order_by'} if ( ! $is_summary && defined $self->{'_order_by'} ); return @elmnts ? "ORDER BY " . join ( ", ", @elmnts ) : (); } sub _sql_limit_clause { my $self = $_[0]; return $self->{'_limit'} ? 'LIMIT ' . $self->{'_limit'} : (); } sub sql_params { my $self = $_[0]; my @params = @{$self->_traverse_from_parent( sub { @{ $_[0]->{'_filter_params'} } } ) }; push @params, @{ $self->{'_filter_params'} }; return \@params; } sub _as_sql { my $self = $_[0]; return join( "\n", $self->_sql_select_clause(), $self->_sql_from_clause(), $self->_sql_where_clause(), $self->_sql_group_by_clause(), $self->_sql_order_by_clause(), $self->_sql_limit_clause(), '' ); } sub _as_summary_sql { my $self = $_[0]; return join( "\n", $self->_sql_select_clause( 1 ), $self->_sql_from_clause( 1 ), $self->_sql_where_clause( 1 ), $self->_sql_group_by_clause( 1 ), $self->_sql_order_by_clause( 1 ), '' ); } =pod =head2 execute() This method executes the query through the database interface and returns an instance of Lire::DlfResult to obtain the data. =cut sub execute { my ( $self, $store ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); foreach my $stream ( @{ $self->joined_streams() } ) { croak "store doesn't contain a '$stream' stream" unless $store->has_dlf_stream( $stream ); } return Lire::DlfResult->new( $self, $self->_as_sql(), $store ); } =pod =head2 execute_summary() Same as the execute() except that the query is executed as a summary query. =cut sub execute_summary { my ( $self, $store ) = @_; check_object_param( $store, 'store', 'Lire::DlfStore' ); foreach my $stream ( @{ $self->joined_streams() } ) { croak "store doesn't contain a '$stream' stream" unless $store->has_dlf_stream( $stream ); } return Lire::DlfResult->new( $self, $self->_as_summary_sql(), $store ); } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfQuery(3pm) Lire::DlfStream(3pm) Lire::DlfStore(3pm) =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <Wolfgang.Sourdeau@Contre.COM> =head1 VERSION $Id: DlfQuery.pm,v 1.44 2006/07/23 13:16:28 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/ReportSection.pm������������������������������������������������������������0000644�0001750�0001750�00000015761�10460673255�014760� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::ReportSection; use strict; use Carp; use Lire::Report::Section; use Lire::DlfSchema; use Lire::Utils qw/check_object_param check_param/; use Lire::I18N qw/dgettext/; use Locale::TextDomain 'lire'; =pod =head1 NAME Lire::ReportSection - API to report configuration's section =head1 SYNOPSIS use Lire::ReportConfig; use Lire::ReportSection; my $report_cfg = new Lire::ReportConfig( "www" ); my $section = new Lire::ReportSection( "www", "General" ); $report_cfg->add_section( $section ); =head1 DESCRIPTION This class offers an object oriented API to report configuration's section. It offers methods to access and modify the section's attribute. =head1 CONSTRUCTOR =head2 new( $superservice, [$title] ) Creates a new Lire::Section object which will contains report specifications of the $superservice superservice. The section's title will be set to the value of $title. =cut sub new { my ( $class, $super, $title ) = @_; check_param( $super, 'superservice', sub { Lire::DlfSchema->has_superservice( $_[0] ) }, 'invalid superservice' ); return bless { '_superservice' => $super, '_filters' => [], '_title' => $title || "Section", '_reports' => [], }, $class; } =pod =head1 OBJECT METHODS =head2 superservice() Returns this section's superservice. =cut sub superservice { my ( $self ) = @_; return $self->{'_superservice'}; } =pod =head2 title([$title]) Return's the current section's title. When the $title parameter is used, it will set the section's title to a new value. =cut sub title { my ( $self, $title ) = @_; if ( defined $title ) { $self->{'_title'} = $title; } return dgettext( "lire-$self->{'_superservice'}", $self->{'_title'} ); } =pod =head2 filters() Returns this section's filter specifications as an array of Lire::FilterSpec objects. Those filter specifications will be used by all of this section's report specifications in addition to the filter specification they may already be using. =cut sub filters { my ( $self ) = @_; return @{ $self->{'_filters'} }; } =pod =head2 add_filter($filter_spec) Adds the $filter_spec filter specification to this section's list. The $filter_spec parameter must be an instance of Lire::FilterSpec or one of its descendants. This method will die if the filter specification's schema isn't compatible with this section's superservice. =cut sub add_filter { my ( $self, $filter_spec ) = @_; check_object_param( $filter_spec, 'filter_spec', 'Lire::FilterSpec' ); # Make sure all the report's schema are compatible # with with this filter my $schema = $filter_spec->schema()->id(); foreach my $r ( $self->reports() ) { croak "filter ", $filter_spec->id(), "'s schema is incompatible ", "with report ", $r->id(), "\n" unless $r->schema()->is_schema_compatible( $schema ); } push @{$self->{'_filters'}},$filter_spec; return; } =pod =head2 reports() Returns this section's report specifications as an array of Lire::ReportSpec objects. =cut sub reports { my ( $self ) = @_; return @{ $self->{'_reports'} }; } =pod =head2 add_report( $report_spec ) Adds the $report_spec report specification to this section. This method will die if the report specification's schema isn't compatible with this section's superservice. =cut sub add_report { my ( $self, $report ) = @_; check_object_param( $report, 'report', 'Lire::ReportSpec' ); croak "can't add a ReportSpec without a subreport_id" unless $report->subreport_id(); croak ( "report is of wrong superservice: ", $report->superservice() , " != ", $self->superservice() ) if $self->superservice() ne $report->superservice(); # Make sure the report's schema is compatible # with all the filters' schema my $schema = $report->schema(); foreach my $f ( $self->filters() ) { croak "report ", $report->id(), "'s schema is incompatible with filter ", $f->id(), "\n" unless $schema->is_schema_compatible( $f->schema()->id() ); } push @{$self->{'_reports'}},$report; return; } # create_report_section # called by Lire::ReportConfig::create_report() sub create_report_section { my ( $self, $report ) = @_; check_object_param( $report, 'report', 'Lire::Report' ); my $section = new Lire::Report::Section( $self->title() ); $report->add_section( $section ); if ( $self->filters() ) { my @filters = map { $_->expanded_display_title() } $self->filters(); my $desc = "<para>" . __n( "Applied filter in this section: ", "Filters applied in this section:", scalar @filters ); $desc .= "\n" if @filters > 1; if ( @filters == 1 ) { $desc .= $filters[0]; } else { $desc .= " <itemizedlist spacing=\"compact\">\n"; foreach my $filter ( @filters ) { $desc .= " <listitem>\n <para>$filter</para>\n </listitem>\n"; } $desc .= " </itemizedlist>\n"; } $desc .= "</para>\n"; $section->description( $desc ); } foreach my $spec ( $self->reports() ) { my $subreport = $spec->create_subreport(); $section->add_subreport( $subreport ); } return $section; } # Factory method for the Configuration API. sub new_from_config { my ( $self, $value ) = @_; my $def = $value->Lire::Config::Dictionary::as_value(); my $section = new Lire::ReportSection( $def->{'superservice'}, $def->{'title'} ); foreach my $filter ( @{$def->{'filters'}} ) { $section->add_filter( $filter ); } foreach my $spec ( @{$def->{'specs'}} ) { $section->add_report( $spec ); } return $section; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::ReportConfig(3pm), Lire::ReportSpec(3pm), Lire::FilterSpec(3pm) Lire::Report::Section(3pm), Lire::Config::ReportSectionSpec(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: ReportSection.pm,v 1.25 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ���������������lire-2.1.1/all/lib/Lire/Report.pm�������������������������������������������������������������������0000644�0001750�0001750�00000025140�10460673255�013423� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Report; use strict; use Carp; use POSIX qw/ strftime /; use Lire::DataTypes qw/ check_superservice check_number /; use Lire::I18N qw/ set_fh_encoding /; use Lire::Utils qw/ xml_encode check_param check_object_param /; =pod =head1 NAME Lire::Report - Interface to a Lire report. =head1 SYNOPSIS use Lire::ReportParser::ReportBuilder; my $parser = new Lire::ReportParser::ReportBuilder; my $report = $parser->parse( "report.xml" ); print $report->superservice(), " report\n"; print "Generated on ", scalar( localtime( $report->date() ) ), "\n"; print "Timespan starts on ", scalar( localtime( $report->timespan_start() ) ), "\n"; print "Timespan ends on ", scalar( localtime( $report->timespan_start() ) ), "\n"; foreach my $s ( $report->sections() ) { print "Section: '", $s->title(), "' has ", scalar $s->subreports(), " subreports in it\n"; } =head1 DESCRIPTION This module offers an API to the report generated by Lire. The Lire::ReportParser::ReportBuilder(3pm) can be used to create a Lire::Report object from an XML file that complies with the Lire Report Markup Language DTD. =head1 CONSTRUCTOR A Lire::Report object can be built from an XML report file, from the new() method or from a Lire::ReportConfig object. =head2 new( [ $timespan_period ], [ $timespan_start ], [ $timespan_end ] ) Creates a new Lire::Report. The $timespan_period, $timespan_start and $timespan_end parameters initialize the attributes of the same name. =cut sub new { my ( $class, $period, $start, $end ) = @_; my $self = bless { '_version' => "2.1", '_generator' => __PACKAGE__ . "(3pm)", '_date' => time, '_start' => undef, '_end' => undef, '_period' => undef, '_sections' => [], }, $class; $self->timespan_period( $period ) if defined $period; $self->timespan_start( $start ) if defined $start; $self->timespan_end( $end ) if defined $end; return $self; } =pod =head1 OBJECT METHODS =head2 version() Returns the version number of the report format which was used in the external representation of this report. The current version is 2.1. =cut sub version { return $_[0]{'_version'}; } =pod =head2 generator([$generator) Returns the generator string that will be outputted in comments when the write_report() method is used. One can change that value by passing a new value through the $generator parameter. =cut sub generator { $_[0]{'_generator'} = $_[1] if defined $_[1]; return $_[0]{'_generator'}; } =pod =head2 date( [ $new_date ] ) Returns (and optionanly changes) the date in seconds since epoch on which this report was generated. =cut sub date { my ( $self, $date ) = @_; if ( @_ == 2 ) { check_param( $date, 'date', \&check_number, "'date' parameter should be a number of seconds since the epoch" ); $self->{'_date'} = $date; } return $self->{'_date'}; } =pod =head2 timespan_period( [ $new_period ] ) Returns (and optionnally changes) the period of the report. The period can be 'hourly', 'daily', 'weekly', 'monthly' or 'yearly'. When the period is undef, it is an arbitrary period. =cut sub timespan_period { my ( $self, $period ) = @_; if ( @_ == 2 ) { check_param( $period, 'period', qr/^(hourly|daily|weekly|monthly|yearly)$/, "'period' parameter should be one of 'hourly', 'daily', 'weekly', 'monthly' or 'yearly'" ) if defined $period; $self->{'_period'} = $period; } return $self->{'_period'}; } =pod =head2 timespan_start( [ $new_start ] ) Returns (and optionnally changes) the start of the timespan covered by this report in seconds since epoch. =cut sub timespan_start { my ( $self, $start ) = @_; if ( @_ == 2 ) { if ( $start ) { check_param( $start, 'start', \&check_number, "'start' parameter should be a number of seconds since the epoch" ); croak "'start' parameter is greater than timespan_end()" if $self->{'_end'} && $start > $self->{'_end'}; } $self->{'_start'} = $start ? $start : undef; } return $self->{'_start'}; } =pod =head2 timespan_end( [ $new_end ] ) Returns (and optionnally changes) the end of the timespan covered by this report in seconds since epoch. =cut sub timespan_end { my ( $self, $end ) = @_; if ( @_ == 2 ) { if ( $end ) { check_param( $end, 'end', \&check_number, "'end' parameter should be a number of seconds since the epoch" ); croak "'end' parameter is smaller than timespan_start()" if $self->{'_start'} && $end < $self->{'_start'}; } $self->{'_end'} = $end ? $end : undef; } return $self->{'_end'}; } =pod =head2 title( [$title] ) Returns the report's title, if it has one. If the $title is parameter is set, the report's title will be set to this new value. =cut sub title { $_[0]{'title'} = $_[1] if @_ == 2; return $_[0]{'title'}; } =pod =pod =head2 description( [$new_desc] ) Returns the report description. This description is encoded in DocBook XML. If the $description parameter is set, this method will set the description to this new value. If the $description parameter is undef, that description will be removed. =cut sub description { $_[0]->{'description'} = $_[1] if @_ == 2; return $_[0]->{'description'}; } =pod =head2 sections( ) Returns the report's sections as an array. This will be an array of Lire::Report::Section objects. =cut sub sections { return @{$_[0]{'_sections'}}; } =pod =head2 add_section( $section ) Adds a section to this report. The $section parameter should be a Lire::Report::Section object. =cut sub add_section { my ( $self, $section ) = @_; check_object_param( $section, 'section', 'Lire::Report::Section' ); push @{$self->{'_sections'}}, $section; return; } =pod =head2 subreport_by_id( $id ) Returns the Lire::Report::Subreport object with $id. Returns undef when there is no subreport with that ID. =cut sub subreport_by_id { my ( $self, $id ) = @_; check_param( $id, 'id' ); foreach my $section ( @{$self->{'_sections'}} ) { foreach my $subreport ( $section->subreports() ) { return $subreport if $subreport->id() eq $id; } } return undef; } =pod =head2 schemas() Returns an array reference containing all the schemas used by this report. =cut sub schemas { my $self = $_[0]; my %schemas = (); foreach my $sect ( $self->sections() ) { foreach my $sub ( $sect->subreports() ) { foreach my $id ( @{$sub->schemas()} ) { $schemas{$id} = 1; } } } return [ sort keys %schemas ]; } =pod =head2 write_report( [FH] ); Write the report in XML format on the FH filehandle or STDOUT if omitted. This method takes care of adding stuff like the XML header C<E<lt>?xml version=[...]>. It encodes the XML report in UTF-8, using Lire::I18N::set_fh_encoding(). =cut sub write_report { my ( $self, $fh ) = @_; $fh ||= \*STDOUT; set_fh_encoding( $fh, 'UTF-8' ); my $time = strftime '%Y-%m-%d %H:%M:%S %Z', localtime $self->date(); my $period_string = ""; if ( $self->timespan_start() ) { my $stime = strftime( '%Y-%m-%d %H:%M:%S %Z', localtime $self->timespan_start() ); my $etime = strftime( '%Y-%m-%d %H:%M:%S %Z', localtime $self->timespan_end() ); $period_string = "$stime - $etime"; } else { $period_string = "Unknown Period"; } print $fh <<EOF; <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V$self->{'_version'}//EN" "http://www.logreport.org/LRML/$self->{'_version'}/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" xmlns:lrcml="http://www.logreport.org/LRCML/" version="$self->{'_version'}"> <!-- generated by $self->{'_generator'} --> EOF print $fh " <lire:title>", xml_encode( $self->title() ), "</lire:title>\n" if defined $self->title(); print $fh ' <lire:date time="', $self->{'_date'}, '">', $time, "</lire:date>\n"; { no warnings 'uninitialized'; print $fh ' <lire:timespan ', ( $self->{'_period'} ? "period=\"$self->{'_period'}\" " : "" ), 'start="', $self->{'_start'}, '" end="', $self->{'_end'}, '">', $period_string, "</lire:timespan>\n"; } print $fh " <lire:description>", $self->description(), "</lire:description>\n\n" if ( $self->description() ); foreach my $s ( $self->sections() ) { $s->write_report( $fh, 1 ); } print $fh "</lire:report>\n"; return; } # Creates an identifier for Subreport's type $type. # This creates an ID that will make sure that the # subreport would be merged identically than with the # previous merging algorithm which didn't merge by id. sub create_subreport_id { my ( $self, $type ) = @_; $self->{'_id_cache'}{$type} ||= 0; return $type . "." . $self->{'_id_cache'}{$type}++; } =pod =head2 delete( ) Removes all circular references so that the object can be freed. =cut sub delete { my $self = $_[0]; foreach my $s ( $self->sections() ) { foreach my $r ( $s->subreports() ) { $r->delete(); } } return; } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::ReportParser::ReportBuilder(3pm) Lire::Report::Section(3pm) Lire::Report::Subreport(3pm) Lire::Report::Entry(3pm) Lire::Report::Group(3pm) Lire::ReportParser(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Report.pm,v 1.35 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002, 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Syslog.pm�������������������������������������������������������������������0000644�0001750�0001750�00000054507�10460673256�013442� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Syslog; use strict; use Time::Local; use Lire::Logger qw/ lr_debug lr_info lr_err /; use Lire::Time qw/ syslog2cal clf2cal date2cal getMonthName /; use vars qw/ $LTIME @syslog_flavours $debug /; BEGIN { $LTIME = [ localtime ]; $debug = 0; } # Function bust be defined, so the assignment can't go in the # BEGIN block # # Order is important since the first that succeeds win. So when # a format is a subformat of another (i.e. classic to sol8) # put the longer format first # @syslog_flavours = ( [ "Solaris 8 syslog daemon", \&parse_sol8_syslog ], [ "BSD syslog daemon", \&parse_bsd_syslog ], [ "BSD timestamp-only syslog daemon", \&parse_bsd_timestamp_syslog ], [ "Netscape Messaging Server logging daemon", \&parse_nms_syslog ], [ "SunONE Messaging Server logging daemon", \&parse_s1ms_syslog ], [ "Unknown syslog daemon with year and code", \&parse_unknown_syslog ], [ "WebTrends syslog daemon", \&parse_wt_syslog ], [ "Kiwi (ISO format) syslog daemon", \&parse_kiwi_iso_syslog ], # Rationale for putting the US format before the regulard DD-MM format # altough we will choose the wrong US format 40% of the time (144 days # on 365): US citizens seems very fond of their format and non-US # are more likely to pick the ISO format (this is completely intuitive and # not based on any evidence). Anyway, we did receive more logs in the # US date format. [ "Kiwi (US format) syslog daemon", \&parse_kiwi_us_syslog ], [ "Kiwi (DD-MM-YYYY format) syslog daemon", \&parse_kiwi_ddmm_syslog ], [ "Sendmail Switch log daemon", \&parse_sendmail_switch_syslog ], ); #------------------------------------------------------------------------ # Constructor new() # # Using one parser object returning record in hash is nearly 50% faster # then using one object by syslog record. # # Testing on 22410 syslog lines # Benchmark: timing 10 iterations of 1 line = 1 object, parser object... # 1 line = 1 object: 24 wallclock secs (24.23 usr + 0.01 sys = 24.24 CPU) @ 0.41/s (n=10) # parser object: 17 wallclock secs (16.52 usr + 0.00 sys = 16.52 CPU) @ 0.61/s (n=10) # s/iter 1 line = 1 object parser object # 1 line = 1 object 2.42 -- -32% # parser object 1.65 47% -- # sub new { my $self = shift; my $class = ref($self) || $self; bless $self = { 'syslog_parse_func' => \&guess_syslog_format, }, $class; return $self; } #------------------------------------------------------------------------ # Function debug( @msg ) # # Logs @msg at debug level if debugging is enable sub debug(@) { lr_debug( __PACKAGE__, ": ", @_ ) if $debug; } #------------------------------------------------------------------------ # Function decode_facility_level($code) # # Determines from an encoded numeric code the syslog level and facility # # Returns an array ($facility, $level) # my @levels = qw/emerg alert crit err warning notice info debug/; my @facilities = qw/kern user mail daemon auth syslog lpr news uucp cron authpriv ftp ntp authaudit authalert cron local0 local1 local2 local3 local4 local5 local6 local7/; sub decode_priority($) { my $priority = shift; die "encoded priority should be between 0 and 191: $priority\n" unless $priority >= 0 && $priority <= 191; my $level_idx = $priority % 8; my $facility_idx = ($priority - $level_idx) / 8; return ( $facilities[$facility_idx], $levels[$level_idx]); } #------------------------------------------------------------------------ # Function extract_process( $rec ) # # This function will try to extract process and process id information # from the message. # It will also remove extra timestamp information from the messages' content # (often encountered with Cisco devices, these look like e.g. # # Oct 31 09:00:53 192.168.0.223 83843: *Mar 8 17:58:46: # %SEC-6-IPACCESSLOGP: list ... # # It returns the modified syslog structure sub extract_process { my ( $rec ) = @_; if ( $rec->{'content'} =~ m!^ (?:\d+:\s)? # Sequence number (?:\d[wdhms\d]+:\s)? # Another router info: 2w5h: # Remove extra timestamp as sometimes sent by network devices # MMM DD [YYYY] HH:MM:SS[.MSEC] [TZ]: # systems which are not NTP synced have a leading * # (Tnx anderson and Edwin Groothuis) (?:\*?\w\w\w\s+\d\d?\s(?:\d+\s+)?[\d:.]+(?:\s[a-z]{3})?:\s)? ([^:\[]+) # Process (?:\[(\d+)\])?:\s+ # Process ID; may be undef (.*) # Actual message $!x ) { $rec->{'process'} = $1; $rec->{'pid'} = $2; $rec->{'content'} = $3; } # Otherwise leave untouched $rec; } #------------------------------------------------------------------------ # Method guess_syslog_format( $line ) # # This function is called on the first line parsed by the object. # # It tries to match the line according to different syslog style # and will setup the syslog_parse_func attribute to point to the # correct parser for that syslog style. # # Next parse are going to go directly to the correct parser function. sub guess_syslog_format { my($self,$line) = @_; foreach my $flavour ( @syslog_flavours ) { # Try to parse each in turn # First that matches is the good one debug( "trying $flavour->[0] syslog flavour" ); my $rec = eval { $flavour->[1]->( $self, $line ) }; unless ( $@ ) { lr_info( __PACKAGE__, ": log seems from $flavour->[0]" ); $self->{'syslog_parse_func'} = $flavour->[1]; return $rec; } else { debug( $@ ); } } # This will aborts the program eval { lr_err( <<EOM ); }; '$line' wasn't recognized as a valid syslog format. If this indeed comes from a syslog variant, please contact bugs\@logreport.org with your version of syslog so that support can be added for it. EOM print STDERR $@; exit 1; } #------------------------------------------------------------------------ # Method parse_bsd_syslog ($line) # # Parse classic BSD syslog daemon messages: # # Nov 7 09:00:49 imrldmz1 sendmail[29681]: .... sub parse_bsd_syslog { my ( $month, $day, $time, $hostname, $content ) = ( $_[1] =~ m/^ \s* (\w\w\w)\s\s? # Month (\d\d?)\s # Day ([\d:.]+)\s # Time ([\w.-]+)\s # Hostname (.*) # Message $/x ) or die "invalid BSD syslog line: $_[1]\n"; extract_process( { 'timestamp' => syslog2cal( $month, $day, $time, $LTIME ), 'hostname' => $hostname, 'content' => $content, } ); } #------------------------------------------------------------------------ # Method parse_nms_syslog( $line ) # # Parse messages log through the logging daemon that comes with # Netscape Messaging Server # # [01/Nov/2001:08:27:44 +0100] titan popd[2864]: General Information: ... # sub parse_nms_syslog { my ( $date, $hostname, $process, $pid, $facility, $level, $content ) = ( $_[1] =~ m/^ \s* (\[.*?\])\s+ # Date in common log format ([\w.-]+)\s # Hostname ([^:\[]+) # Process (?:\[(\d+)\])?:\s+ # Process ID; may be undef (\w+)\s+ # Facility (\w+):\s+ # Level (.*) # Message $/x ) or die "invalid Netscape Messaging Server syslog line: $_[1]\n"; return { 'timestamp' => clf2cal( $date ), 'hostname' => $hostname, 'process' => $process, 'content' => $content, 'pid' => $pid, 'facility' => $facility, 'level' => $level, }; } #------------------------------------------------------------------------ # Method parse_s1ms_syslog( $line ) # # Parse messages log through the logging daemon that comes with # SunONE Messaging Server # # 18-Nov-2002 11:53:36.49 72bb.3.1 tcp_local ims-ms E 1 ... # 18-Nov-2002 12:37:42.79 72bb.0b.4 tcp_intranet tcp_local E 1 ... # 18-Nov-2002 13:30:17.82 7304.2.1 tcp_local D 2 ... # 18-Nov-2002 15:29:11.31 72bb.8.13 tcp_intranet J 0 ... # sub parse_s1ms_syslog { my ( $day, $month, $year, $time, $msec, $pid, $count, $in_chan, $out_chan, $entry, $content ) = ( $_[1] =~ m/^(\d{2})-([A-Z]{1}[a-z]{2})-(\d{4})\s+ # Date in format DD-mmm-YYYY (\d{2}:\d{2}:\d{2})(\.\d+)\s+ # Time in format hh:mm:ss.ms ([0-9a-f]+) # pid in hexa (\.[0-9a-f]+\.\d+)\s+ # count (in hexa) and thread ([a-z_ -]{12})\s # source channel ([a-z_ +-]{12})\s # destination channel ([A-Z]{1,3})\s+ # type of entry (.*) # Message $/x ) or die "invalid SunONE Messaging Server syslog line: $_[1]\n"; $in_chan =~ s/ +//g; $out_chan =~ s/ +//g; return { 'timestamp' => syslog2cal( $month, $day, $time, $LTIME ), 'pid' => $pid, 'count' => $count, 'in_chan' => $in_chan, 'out_chan' => $out_chan, 'entry' => $entry, 'content' => $content, }; } #------------------------------------------------------------------------ # Method parse_sol8_syslog ($line) # # Parse Solaris 8 syslog daemon messages: # # Nov 7 09:00:49 imrldmz1 sendmail[29681]: [ID 801593 mail.info] ... sub parse_sol8_syslog { my ( $month, $day, $time, $hostname, $process, $pid, $id, $facility, $level, $content ) = ( $_[1] =~ m/^ \s* (\w\w\w)\s+ # Month (\d\d?)\s+ # Day ([\d:.]+)\s+ # Time ([\w.-]+)\s # Hostname ([^:\[]+) # Process (?:\[(\d+)\])?:\s # Process ID; may be undef \[ID\s # Special Solaris 8 identifier (\d+)\s # Identifier, whatever that means ([a-z0-9]+)\.([a-z]+) # Facility.level \]\s+ (.*) # Message $/x ) or die "invalid Solaris 8 syslog line: $_[1]\n"; return { 'timestamp' => syslog2cal( $month, $day, $time, $LTIME ), 'hostname' => $hostname, 'process' => $process, 'content' => $content, 'pid' => $pid, 'identifier' => $id, 'facility' => $facility, 'level' => $level, }; } #------------------------------------------------------------------------ # Method parse_sendmail_switch_syslog # # Parse messages coming from the logging daemon that # comes with Sendmail Switch Pro (as found on WinTel platforms) # # 04/16/02 00:00:03 sendmail(2716): INFO: sub parse_sendmail_switch_syslog { my ( $month, $day, $year, $time, $hostname, $process, $pid, $level, $content ) = ( $_[1] =~ m!^ \s* (\d+)/(\d+)/(\d+)\s+ # MM/DD/YY ([\d:.]+)\s+ # Time ([^:()]+) # Process (?:\((\d+)\))?:\s+ # Process ID; may be undef (\w+):\s+ # Level (.*) # Message $!x ) or die "invalid Sendmail Switch syslog line: $_[1]\n"; return { 'timestamp' => date2cal( $year+2000, getMonthName($month-1), $day, $time), 'hostname' => $hostname, 'process' => $process, 'pid' => $pid, 'level' => lc $level, 'content' => $content, }; } #------------------------------------------------------------------------ # Method parse_bsd_timestamp_syslog ($line) # # Parse messages which only contains the BSD timestamp: # # Jul 22 00:01:14: sendmail[1204]: sub parse_bsd_timestamp_syslog { my ( $month, $day, $time, $content ) = ( $_[1] =~ m/^ \s* (\w\w\w)\s+ # Month (\d\d?)\s # Day ([\d:.]+)\s # Time (.*) # Message $/x ) or die "invalid BSD timestamp syslog line: $_[1]\n"; extract_process( { 'timestamp' => syslog2cal( $month, $day, $time, $LTIME ), 'content' => $content, } ); } #------------------------------------------------------------------------ # Method parse_unknown_syslog ($line) # # Parse messages from rfc 3164-compliant syslog daemons that keep the encoded # facility and has a year: # # <166>Jul 22 2002 00:01:14: %PIX-6-302001: sub parse_unknown_syslog { my ( $priority, $month, $day, $year, $time, $content ) = ( $_[1] =~ m/^ \s* <(\d+)> # Facility and level encoded (\w\w\w)\s+ # Month (\d\d?)\s # Day (\d\d\d\d)\s # Year ([\d:.]+)\s # Time (.*) # Message $/x ) or die "invalid unknown syslog with year and code line: $_[1]\n"; my ($facility, $level) = decode_priority( $priority ); extract_process( { 'timestamp' => syslog2cal( $month, $day, $time, $LTIME ), 'content' => $content, 'facility' => $facility, 'level' => $level, } ); } #------------------------------------------------------------------------ # Method parse_wt_syslog( $line ) # # Parses syslog message from WebTrends syslog daemon # # Example: WTsyslog[2002-08-23 12:23:55 ip=10.161.2.250 pri=6] <189>49288: Aug 23 12:39:31.427 est: %SYS-5-CONFIG_I: sub parse_wt_syslog { my ( $year, $month, $day, $time, $hostname, $wtpriority, $priority, $content ) = ( $_[1] =~ m/^ \s* WTsyslog\[(\d\d\d\d)- # Year (\d\d)- # Month (\d\d)\s # Day ([\d:.]+)\s # Time ip=([\d.]+)\s # Hostname pri=(\d+)\]\s # WT Priority (?:<(\d+)>)? # Encoded priority (.*) # Message $/x ) or die "invalid WebTrends syslog line: $_[1]\n"; my ($facility, $level) = decode_priority( $priority ); extract_process( { 'timestamp' => date2cal( $year, getMonthName($month-1), $day, $time ), 'hostname' => $hostname, 'content' => $content, 'facility' => $facility, 'level' => $level, } ); } #------------------------------------------------------------------------ # Method parse_kiwi_iso_syslog( $line ) # # Parses syslog message from Kiwi syslog daemon in ISO format # # Kiwi format ISO yyyy-mm-dd (Tab delimited) # Format: DateTime (YYYY-MM-DD HH:MM:SS) [TAB] Level (Facility.Level) [TAB] Host name [TAB] Message text # #Example: 2002-07-22 12:34:56 [TAB] Local5.Debug [TAB] firewall-inside [TAB] prot=UDPf port=53 dst=203.25.36.47 src=192.168.1.2 bytes=64 sub parse_kiwi_iso_syslog { my ( $year, $month, $day, $time, $facility, $level, $hostname, $content ) = ( $_[1] =~ m/^ \s* (\d\d\d\d)- # Year (\d\d)- # Month (\d\d)\s # Day ([\d:.]+)\t # Time (\w+)\. # Facility (\w+)\t # Level ([\w.-]+)\t # Hostname (.*) # Message $/x ) or die "invalid Kiwi (ISO format) syslog line: $_[1]\n"; extract_process( { 'timestamp' => date2cal( $year, getMonthName($month-1), $day, $time ), 'hostname' => $hostname, 'content' => $content, 'facility' => $facility, 'level' => $level, } ); } #------------------------------------------------------------------------ # Method parse_kiwi_us_syslog( $line ) # # Parses syslog message from Kiwi syslog daemon in US format # # Kiwi format US mm-dd-yyyy (Tab delimited) # Format: DateTime (MM-DD-YYYY HH:MM:SS) [TAB] Level (Facility.Level) [TAB] Host name [TAB] Message text # #Example: 07-22-2002 12:34:56 [TAB] Local5.Debug [TAB] firewall-inside [TAB] prot=UDPf port=53 dst=203.25.36.47 src=192.168.1.2 bytes=64 sub parse_kiwi_us_syslog { my ( $month, $day, $year, $time, $facility, $level, $hostname, $content ) = ( $_[1] =~ m/^ \s* (\d\d)- # Month (\d\d)- # Day (\d\d\d\d)\s # Year ([\d:.]+)\t # Time (\w+)\. # Facility (\w+)\t # Level ([\w.-]+)\t # Hostname (.*) # Message $/x ) or die "invalid Kiwi (DD-MM-YYYY format) syslog line: $_[1]\n"; die "not a MM-DD-YYYY date: $month-$day-$year\n" unless $month >=1 && $month <= 12; extract_process( { 'timestamp' => date2cal( $year, getMonthName($month-1), $day, $time ), 'hostname' => $hostname, 'content' => $content, 'facility' => $facility, 'level' => $level, } ); } #------------------------------------------------------------------------ # Method parse_kiwi_ddmm_syslog( $line ) # # Parses syslog message from Kiwi syslog daemon in the DD-MM-YYYY date format. # # Kiwi format mm-dd-yyyy (Tab delimited) # Format: DateTime (DD-MM-YYYY HH:MM:SS) [TAB] Level (Facility.Level) [TAB] Host name [TAB] Message text # #Example: 22-07-2002 12:34:56 [TAB] Local5.Debug [TAB] firewall-inside [TAB] prot=UDPf port=53 dst=203.25.36.47 src=192.168.1.2 bytes=64 sub parse_kiwi_ddmm_syslog { my ( $day, $month, $year, $time, $facility, $level, $hostname, $content ) = ( $_[1] =~ m/^ \s* (\d\d)- # Day (\d\d)- # Month (\d\d\d\d)\s # Year ([\d:.]+)\t # Time (\w+)\. # Facility (\w+)\t # Level ([\w.-]+)\t # Hostname (.*) # Message $/x ) or die "invalid Kiwi (DD-MM-YYYY format) syslog line: $_[1]\n"; die "not a DD-MM-YYYY date: $day-$month-$year\n" unless $month >=1 && $month <= 12; extract_process( { 'timestamp' => date2cal( $year, getMonthName($month-1), $day, $time ), 'hostname' => $hostname, 'content' => $content, 'facility' => $facility, 'level' => $level, } ); } #------------------------------------------------------------------------ # Method parse($line) # # Delegate to the appropriate syslog parse function sub parse { $_[0]->{'syslog_parse_func'}->( @_ ); } 1; __END__ =pod =head1 NAME Lire::Syslog - syslog style lines parser =head1 SYNOPSIS use Lire::Syslog; my $parser = new Lire::Syslog; my $rec = $parser->parse( $line ); =head1 DESCRIPTION This module defines objects able to parse logs coming from several flavours of logging daemon. It currently supports the following syslog file formats: =over =item Classic BSD syslog daemon The "classic" BSD syslog format: MMM DD HH:MM:SS Hostname Message =item Solaris 8 syslog daemon The Solaris 8 syslog daemon also includes the facility and level: MMM DD HH:MM:SS Hostname Process[Pid]: [ID DDDDDD Facility.Level] Message =item Netscape Messaging Server logging daemon The syslog daemon that comes with Netscape Messaging Server uses a date in common log format: [DD/MMM/YYYY:HH:MM:SS +ZZZZ] Hostname Process[Pid]: Facility Level: Message =item WebTrends syslog daemon The format used by the syslog daemon that comes with WebTrends: WTsyslog[YYYY-MM-DD HH:MM:SS ip=HOSTNAME pri=WT_PRIORITY] <XX>Message =item Kiwi Syslog (ISO date format) The ISO log file formats used by the Kiwi Syslog daemon (http://www.kiwisyslog.com/info_sysd.htm), a logging daemon often encountered on Win32 platforms: YYYY-MM-DD HH:MM:SS [TAB] Facility.Level [TAB] Hostname [TAB] Message =item Kiwi Syslog (US date format) The US date format used by the Kiwi Syslog daemon: MM-DD-YYYY HH:MM:SS [TAB] Facility.Level [TAB] Hostname [TAB] Message =item Kiwi Syslog (DD-MM-YYY date format) The DD-MM-YYYY date format used by the Kiwi Syslog daemon: DD-MM-YYYY HH:MM:SS [TAB] Facility.Level [TAB] Hostname [TAB] Message =item Sendmail Switch logging daemon The format used by the logging daemon coming with Sendmail Switch on Win32 platforms: MM/DD/YY HH:MM:SS Process(Pid): Level: Message =item RFC 3164-compliant Syslog daemon A format from RFC 3164-compliant Syslog daemons which includes the encoded priority and the year in the date. RFC 3164 defines the "BSD Syslog Protocol". <Priority>MMM DD YYYY HH:MM:SS: Process[Pid]: Message =back The first time the parse() method is used, the parser will try each of the supported formats to detect the syslog format. If no format matches, the module will call lr_err() and abort the program. Each other parse() invocation will use the same format. The parse() method will return an hash reference which contains the following keys: =over =item timestamp The timestamp of the event. =item hostname The name or IP address of the host that sended the message. =item process The "process" that logged the event. Formally, the syslog message doesn't contain a process field but its usually the first word coming before a colon in the message's content. =item pid The PID of the process that logged the event. This is usually what is between [] in the process part of the message. =item identifier This key is only present when the log comes from a Solaris 8 syslog daemon. It contains the identifier that comes after ID in the message. =item facility The syslog facility (kern, mail, local0, etc.) of the message. This isn't supported in all file formats so this key might be unavailable. =item level The syslog level (emerg, info, notice, etc. ) of the message. This isn't supported in all file formats so this key might be unavailable. =item content The actual syslog message (with the process and pid removed). Many network devices will also have another BSD-style timestamp at the beginning of the message. If present, it will also be removed. =back =head1 USAGE package Lire::Foo; use base qw/ Lire::Syslog /; sub parse { my $self = shift; my $line = shift; # this runs parse from Lire::Syslog, setting keys like 'day', 'process' # and 'hostname' my $rec = $self->SUPER::parse($line); $rec->{'foo'} = dosomethingwith( $rec->{'content'} ); return $rec } Now, one can run in a script my $parser = new Lire::Foo(); while ( <> ) { chomp; my $log = $parser->parse( $line ); } which sets $log->{'day'}, ... $log->{'process'} and $log->{'foo'}. =head1 SEE ALSO Lire::Email(3) =head1 AUTHORS Joost van Baal, Francis J. Lacoste. Initial idea by Joost Kooij =head1 VERSION $Id: Syslog.pm,v 1.15 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2000-2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/WeekCalculator.pm�����������������������������������������������������������0000644�0001750�0001750�00000015751�10460673256�015065� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::WeekCalculator; use strict; use Carp; use Time::Local; use POSIX qw/ strftime mktime localtime /; use Lire::Config; use vars qw/ $haveV /; =pod =head1 NAME Lire::WeekCalculator - handle different weeknumbering schemes =head1 SYNOPSIS use Lire::WeekCalculator; my $week_calc = new Lire::WeekCalculator(); my $week_no = $week_calc->week_number( $time ); =head1 DESCRIPTION We support three values for LR_WEEK_NUMBERING: ISO (strftime's %V): week starts on monday; W (week starts on monday) and U (week starts on sunday). See strftime(1). =cut # week numbering voodoo: # in non-iso case, some weeks have two names: # sunday december 30 2001 - saturday jan 5 2002 is known as # 2001's week 53 and 2002's week 00, in the %U case. We use # only the 2001 week 53 name for this (complete) week. Lire # never shows statistics for week 00. A similar case holds # for %W numbering. # # requirements: #We should contruct Lire_number from a date and config, and construct #weekstring from Lire_number and config =pod =head1 CONSTRUCTOR =head2 new( %params ) Creates a new week calculator. The style of week numbering is selected using the C<style> parameter. If that parameter is omitted, it defaults to the style set in 'lr_week_numbering' configuration variable. =cut sub new { my ( $class, %params ) = @_; my $style = $params{'style'} || Lire::Config->get( 'lr_week_numbering' ); my $self = bless { 'style' => $style }, $class; if ( $style eq 'W' ) { # range 00 to 53, week starts at monday $self->{'fmt'} = '%W'; } elsif ( $style eq 'U' ) { # range 00 to 53 # if jan 1 is a sunday, its in week 01, else in week 00. $self->{'fmt'} = '%U'; } elsif ( $style eq 'ISO' ) { # LR_WEEK_NUMBERING is ISO, range 01 to 53, indicate week like # e.g. `2002-W37' $self->{'fmt'} = '%V'; } else { croak "invalid week numbering style: $style (should be W, U or ISO )\n" } $haveV = (strftime('%V', POSIX::localtime(time) ) ne '%V') unless defined $haveV; return $self; } =pod =head2 style() Returns the week numbering style used. This will be either C<U>, C<W> or C<ISO>. =cut sub style { $_[0]{'style'}; } =pod =head2 week_number( $time ) Returns the week number of $time according the current week numbering scheme. The week number returned is between 1 and 53. =cut sub week_number { my ( $self, $time ) = @_; return $self->strfdate( $self->{'fmt'}, localtime $time) + 0; } =pod =head2 week_idx( $time ) Returns the week index of $time according to the week numbering scheme. The week index is Lire specific and is used to normalise computations between different scheme in regards of the first incomplete week of the year. In the ISO case, the week index is always equals to week_number() - 1, for the other style, the week index of the week 0 will be one less than the last week number of the previous year. =cut sub week_idx { my ( $self, $time ) = @_; my $week_idx = $self->week_number( $time ) - 1; if ( $self->{'style'} ne 'ISO' && $week_idx < 0 ) { my $year = (localtime( $time ))[5] + 1900; return $self->last_week_of_year( $year ) - 1; } return $week_idx; } =pod =head2 last_week_of_year($year) Returns the week number of the last week in the year $year. =cut sub last_week_of_year { my ($self, $year) = @_; $year = $year - 1900 if $year >= 1900; # Look into the cache first return $self->{'year_last_week'}{$year} if $self->{'year_last_week'}{$year}; # When using ISO style, the week of December 31st may be # week 1, so we need to find the last assigned week number in # December my $last_week; my $day = 31; do { $last_week = $self->strfdate( $self->{'fmt'}, (0,0,0,$day,11,$year) )+0; $day--; } while ( $last_week < 52 ); return $self->{'year_last_week'}{$year} = $last_week; } =pod =head2 week_start( $year, $week_no ) Returns the epoch time of the first day of week $week_no in year $year when calculated using current style. =cut sub week_start { my ( $self, $year, $week_no ) = @_; my $week1_start = $self->find_year_week1_start_date( $year ); # If week == 0, this will be 7 days before (in the previous year) # the start of week 1 return $week1_start + 86400 * 7 * ($week_no - 1); } =pod =head2 find_year_week1_start_date($year) Returns the date (epoch) at which the first day of the first week of the year $year starts. =cut sub find_year_week1_start_date { my ($self, $year) = @_; $year = $year - 1900 if $year >= 1900; # Look into the cache first return $self->{'week1_start'}{$year} if $self->{'week1_start'}{$year}; # Start the search at the end of the previous year # for ISO case my $year_o = $year; my ($time, $week_no); my $date = 28; my $month = 11; $year = $year_o - 1; do { $time = timelocal( 0, 0, 0, $date, $month, $year ); $week_no = $self->strfdate( $self->{'fmt'}, localtime($time) )+0; $date++; if ( $date == 32 ) { $year++; $month = 0; $date = 1; } } while ( $week_no != 1 ); return $self->{'week1_start'}{$year_o} = $time; } =pod =head2 strformat() Returns a string that can be used as the format specificier in calls to strftime to print the week number of this style. =cut sub strformat { my ( $self ) = @_; return $self->{'style'} eq 'ISO' ? "%G-W%V" : "Week $self->{'fmt'}, %Y"; } =pod =head2 strfdate() Emulates POSIX::strftime() but picks up the %V if the system strftime doesn't support it. Should be called whenever you use format strings that may contain week-of-the-year-codes. =cut sub strfdate { my $self = shift; my $fmt = shift; if(!$haveV and $_[0] =~ /\%V/) { my $d = $_[6] || 7; my @c = localtime(mktime(@_) - ($d-4)*86400); my $v = int($c[7]/7)+1; $v = '0'.$v if $v < 10; $fmt =~ s/\%V/$v/g; } return strftime($fmt, @_) } 1; __END__ =pod =head1 AUTHORS Joost van Baal <joostvb@logreport.org>, Francis J. Lacoste <flacoste@logreport.org>, Wessel Dankers <wsl@logreport.org> =head1 VERSION $Id: WeekCalculator.pm,v 1.16 2006/07/23 13:16:30 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut �����������������������lire-2.1.1/all/lib/Lire/OutputFormat.pm�������������������������������������������������������������0000644�0001750�0001750�00000005252�10460673255�014623� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::OutputFormat; use base qw/Lire::Plugin/; use strict; =pod =head1 NAME Lire::OutputFormat - Base interface for all OutputFormats. =head1 SYNOPSIS use base qw/ Lire::OutputFormat /; =head1 DESCRIPTION The Lire::OutputFormat objects are used to This package defines the interface which is implemented by all the different OutputFormat that Lire is able to produce. It is this object which has the responsability to convert the XML report to its final format. =head1 META INFORMATION METHODS The Lire::OutputFormat interface extends the Lire::Plugin interface, so they must implement all standard meta-information methods (name(), title(), description()). =cut sub type { return 'output_format' } =pod =head2 missing_requirements() This method is queried at runtime to determine if any requirements are missing. It should return an array of messages explaining each missing requirements for the format. =cut sub missing_requirements { return (); } =pod =head1 FORMATTING A REPORT =head2 format_report( $xml_file, $output_file, $format_cfg ) This method should format the XML report contained in $xml_file into the $output_file (or directory). Additional configuration options are passed in the $format_cfg Lire::Config::TypeSpec object specific to the plugin. =cut sub format_report { die ( ref $_[0], "::format_report unimplemented" ); } =pod =head2 mime_report( $xml_file, $format_cfg ) WHen this method is invoked it, the plugin should format the report contained in $xml_file and MIME encapsulate it a MIME::Entity object which is return. Formatting options can be be in the $format_cfg Lire::Config::TypeSpec object. =cut sub mime_report { die ( ref $_[0], "::mime_report unimplemented" ); } 1; __END__ =pod =head1 SEE ALSO Lire::ReportJob(3pm) Lire::OutputJob(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: OutputFormat.pm,v 1.6 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Logger.pm�������������������������������������������������������������������0000644�0001750�0001750�00000010054�10460673255�013365� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Logger; use strict; use base qw/ Exporter /; use vars qw/ @EXPORT $lr_tag /; use File::Basename; =pod =head1 NAME Lire::Logger - Lire's logging interface. =head1 SYNOPSIS Any program: use Lire::Logger qw/ lr_info lr_debug lr_warn /; lr_info( "doing stuff " ); lr_debug( "debugging information" ); lr_warn( "encountered unexpected value: ", $value ); open( CFGFILE, "my.conf" ) or lr_err( "open error: ", $! ); =head1 DESCRIPTION This module contains functions that should be used by everything in the Lire framework which should need logging. =cut BEGIN { my $prog = basename $0; my $super = $ENV{'LR_SUPERSERVICE'} || 'all'; my $service = $ENV{'LR_SERVICE'} || 'all'; my $lr_id = $ENV{'LR_ID'} || "UNSET"; $lr_tag = "$super $service $lr_id $prog"; @EXPORT = qw/ lr_emerg lr_crit lr_err lr_warn lr_notice lr_info lr_debug /; } =pod All logging functions take any number of parameters that will be joined together to form the message (like print(), die(), warn() and friends). =cut sub label_msg { my ( $label, @msg ) = @_; # Maybe remove trailing newline of last part of the message. chomp $msg[$#msg]; # Add $lr_tag err in front of all lines my $msg = join "", @msg, "\n"; $msg =~ s/^/$lr_tag $label /mg; $msg; } =pod =head2 lr_emerg() This logs a message at the C<emerg> level and aborts your program. This probably shouldn't be used. =cut sub lr_emerg { my $msg = label_msg( "emerg", @_ ); die $msg; } =pod =head2 lr_crit() This logs a message at the C<crit> level and aborts your program. This should only be used when something is really broken in the Lire program or the environment. It is used a few places in Lire when assertion that should really never fail (like a DLF file with the wrong number of fields). =cut sub lr_crit { my $msg = label_msg( "crit", @_ ); die $msg; } =pod =head2 lr_err() This logs a message at the C<err> level and usually aborts your program. (It is the equivalent of a die().) The program won't abort if it's used in an eval block. Uses this for error condition. =cut sub lr_err { my $msg = label_msg( "err", @_ ); die $msg; } =pod =head2 lr_warn() This logs a message at the C<warning> level. Perl's builtin warn is mapped to this function. Use this for non-fatal errors. =cut sub lr_warn { my $msg = label_msg( "warning", @_ ); print STDERR $msg; } =pod =head2 lr_notice() This logs a message at the C<notice> level. This should be used for significant informational messages that the user should see. (By default, the user will only see messages at level C<notice> or higher.) =cut sub lr_notice { my $msg = label_msg( "notice", @_ ); print STDERR $msg; } =pod =head2 lr_info() This logs a message at the C<info> level. Use this for general informational messages. =cut sub lr_info { my $msg = label_msg( "info", @_ ); print STDERR $msg; } =pod =head2 lr_debug() This logs a message at the C<debug> level. Use this for debugging messages. =cut sub lr_debug { my $msg = label_msg( "debug", @_ ); print STDERR $msg; } 1; __END__ =pod =head1 SEE ALSO Lire::Program(3pm) =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org> =head1 VERSION $Id: Logger.pm,v 1.10 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2003 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Lire/Field.pm��������������������������������������������������������������������0000644�0001750�0001750�00000010172�10460673255�013172� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Field; use strict; use Lire::DataTypes qw/ check_xml_name check_type is_numeric_type/; use Lire::I18N qw/ dgettext dgettext_para /; use Lire::Utils qw/ check_param /; =pod =head1 NAME Lire::Field - Interface to Dlf field's specification. =head1 SYNOPSIS my $field = $schema->field( 'time' ); print "Name: ", $field->name(), "\n", "Type: ", $field->type(), "\n"; =head1 DESCRIPTION This module represents Dlf field's specifications. You'll get reference to this kind of object when you call the field(), timestamp_field() or fields() methods on a Lire::DlfSchema(3pm) object. You can obtain information about this field by querying its methods. =head1 OBJECT METHODS =cut sub new { my ($class, %params) = @_; check_param( $params{'name'}, 'name', \&check_xml_name, "'name' parameter should be a valid XML name" ); check_param( $params{'type'}, 'type', \&check_type, "'type' parameter should be a valid Lire type" ); return bless { 'name' => $params{'name'}, 'type' => $params{'type'}, 'i18n_domain' => $params{'i18n_domain'} || 'lire', 'pos' => undef, 'description' => $params{'description'}, 'label' => $params{'label'}, }, $class; } =pod =head2 name() Returns the name of the field. =cut sub name { return $_[0]->{'name'}; } =pod =head2 label() Returns the default label that should be used for column containing values from this field. =cut sub label { my $self = $_[0]; return dgettext( $self->{'i18n_domain'}, $self->{'label'} ? $self->{'label'} : $self->{'name'} ); } =pod =head2 pos() Returns the field's position in the record. Field's positions are indexed from 0. =cut sub pos { return $_[0]->{'pos'}; } =pod =head2 type() Returns the field's type. This will be a string describing the type's name as used in the XML specifications. =cut sub type { return $_[0]->{'type'}; } =pod =head2 sql_type() Returns the SQL type that should be used to hold this field's values. =cut sub sql_type { my $self = $_[0]; if ( $self->{'type'} =~ /^(timestamp|date|time)$/ ) { return "TIMESTAMP"; } elsif ( $self->{'type'} =~ /^(bytes|duration)$/ ) { return "NUMBER(10,1)" } elsif ( $self->{'type'} eq "bool" ) { return "NUMBER(1,0)"; } elsif ( $self->{'type'} eq "number" ) { return "NUMBER(10,5)"; } elsif ( $self->{'type'} eq "int" ) { return "NUMBER(10,0)"; } elsif ( $self->{'type'} eq "id" ) { return "INTEGER PRIMARY KEY"; } else { return "VARCHAR(512)"; } } =pod =head2 default() This method is obsolete since field don't have default anymore. =cut sub default { return 'LIRE_NOTAVAIL'; } =pod =head2 description() This method will return the field's description. (This is the content of the description element in the XML specification.) Be aware that this will most likely contains DocBook markup. =cut sub description { return dgettext_para( $_[0]->{'i18n_domain'}, $_[0]->{'description'} ); } # keep perl happy 1; __END__ =pod =head1 SEE ALSO Lire::DlfSchema(3pm) Lire::DataTypes(3pm) =head1 AUTHORS Francis J. Lacoste <flacoste@logreport.org> Wolfgang Sourdeau <wolfgang@logreport.org> =head1 VERSION $Id: Field.pm,v 1.18 2006/07/23 13:16:29 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2001-2004 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/html/����������������������������������������������������������������������������0000755�0001750�0001750�00000000000�11677607767�011761� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/html/lire.png��������������������������������������������������������������������0000644�0001750�0001750�00000005204�10460672576�013330� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR���/���0���#���gAMA�� a���bKGD������ pHYs�� �� ����tIME$s"0t�� IDATx^՚[lgfvg]q[$qMD)} H�PET)xhQ�(%Eh`8'%I߽c^{v K9;RVǕX,!S.f͚H(24 @��7[<[j�XL&^He>^,-@K;ی3!C>dDf l֜`0hy-[U-!/_O -򭣬L)--5 BXG=##f+cخv,n BPЂ\H)dRJXaf6&7#KBn;뺄'@?68`lI_ h 9M~9_FuwQ}R˲D*RMT,/bO:b筬=WM�pe~yϾ|4^ItT#p70lkٱ.`*%@ v|US<qi3TPzZiw ;^=BP!/ȧ,ˍ'afjH֍"]1,˚~޵ |RǶaE1%0-K@w𣯼r0+L ]׿ę|BJ v!Cu͢0ԇ_˳&rƋ=od$NMM)_|ߐR%?1ӲL&^J m>+s͍'KZkYZ@m$)D"*\{<EUUu]K$eY2ɞK!7OWg2'x<>X"yϧj߾drT(Bf,f&b8CknۣJggg|N[5W=QzrQ؅옅}`GN:2Td+](K((3x Hd WK[$3.eK"3nNnW)ol4sL!2,4DS?h*TL[XTDi]�1p$P2MX d'~27gL+-۵.( i%-˪  X%�2~5]gE[z^>=sA(WQAѣeeHzmPY(UMBh42t-MϢ^/}_.noڶa 宻ЂA§N桇rEqILLիNQv䊟8VPW`AQR[ˎݷU+]FUk+at7nY]r%2~xDo/;ZZ.]@w|J�,B�m-?Rge[8 녅8t?&z@uT7J:=-3EͿ{AL:whvݹjxoHH9?0 HlYN팼't:D\z}6ՃC9ror?_0C_2 ҿ&yge9\a^>=&s4 ˟~ʑfb`B/1BҦB}𐕎Fx_e%n/in؀iL W!10r/kkʩS4Ic\ՋqGFHKsVsǻϞ>gLQU/_~K{Ub:3MO2e1qʒ=ye6!4]Pc_}!ѩ)�&H'LSаzxI"c ntv%L 矽j_}eMMlڿ[w<¼lH$:|9˷TJj!i,%ؘa0ayXBGޒԜń _1kYnlol{-8hP4 H`4bšeZKG.8$�I.w_XL[/\ɾPf5}K"|%~(niq&n䋛sF뛾ZRb5mmt*׭fyq/Gqx h~|-=suB^*B8P'h [ Qs'#D;;)^P08_k6�BrxpGF4J"%P`NZxӤ X_)0cEjnT8S)$K{ L$N<$y:'N0q|ΘiY|SԬ]i91 B۶m 麮WT|(/MKRR}nW iD0c )ˤRS+XBS2( a+^pZH)Š4<catE"�jbuuu,y!N>]f0MS!:>>YSe]o(tݦOWVV&Z[[áP?Y?,R����IENDB`��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/html/lire-html.css���������������������������������������������������������������0000644�0001750�0001750�00000010543�10460672576�014300� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������:lang(fr) > Q { quotes: "«" "»" "<" ">" } body { font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 12pt; font-weight: normal; font-style: regular; color: #222222; background: white; text-align: left; top: 0; left: 0; padding: 0; margin: 0; } h2 { font-size: 14pt; font-weight: bold; margin-top: .4em; vertical-align: base; } h3 { color: black; background: #eeeeee; padding: 0; margin: 0; font-size: 12pt; font-weight: normal; text-align: center; padding-left: 1em; padding-right: 1em; } .no-content, span.literal { font-style: italic; } .toc-entry { font-weight: bold; } .admonition { text-decoration: underline; color: black; background: transparent; } var { font-family: Courier New, Courier, Fixed, Mono; font-style: normal; } div.navigation { position: fixed; z-index: 500; top: 20px; left: 65px; } div.title { position: fixed; z-index: 1000; top: 0px; left: 0px; padding: 0; margin: 0; width: 100%; height: 60px; text-align: center; vertical-align: top; border-bottom: 1px solid #aaaaaa; color: black; background: #dddddd; } div.logo { position: fixed; z-index: 500; top: 7px; left: 7px; } img.logo { border: 0px; width: 48px; height: 48px; } div.report-infos { position: relative; color: #777777; background: transparent; top: -1.4em; margin: 0; padding: 0; text-align: center; font-size: 9pt; } div.anchor { margin-top: 70px; } div.toc, div.section { color: black; background: transparent; margin-top: 65px; margin-left: 2em; margin-right: 2em; padding: .5em; } div.para, li { margin: .5em; font-size: 12pt; } div.note { border: 1px solid #444444; padding: .5em; margin: .5em; } div.warning { margin: 2em; color: #ff5555; background: transparent; } dt { text-decoration: underline; margin-left: 1em; } dt:after { content: ':'; } dd { margin-left: 2em; margin-right: 1em; } ol.toc, dt { margin-top: 1em; } ol.toc-section { list-style-type: lower-latin; border-left: 1px solid #444444; } a.link, a[href] { text-decoration: none; border: 1px solid transparent; color: #777777; background: transparent; } a.link:hover, a[href]:hover { border: 1px solid transparent; color: black; background: #ffff55; } a.link:active, a[href]:active { border-left: 1px solid #666622; border-top: 1px solid #666622; border-right: 1px solid #aaaa55; border-bottom: 1px solid #aaaa55; color: black; background: #eeee66; } a.navigation, a.navigation:active, a.navigation:hover { border: 0; width: 24px; height: 24px; color: transparent; background: transparent; } a.logo, a.logo:active, a.logo:hover { border: 0; width: 48px; height: 48px; color: transparent; background: transparent; } div.subreport { margin: 1em; border: 1px solid #eeeeee; overflow: visible; } table { margin: 2em; padding: 0px; cell-spacing: 0px; border-collapse: collapse; border-top: 1px solid black; border-left: 1px solid black; border-right: 2px solid black; border-bottom: 2px solid black; } div.subreport div.description { color: #444444; background: white; margin-left: 2em; } div.chart { margin: 2em; } div.chart img { border: 1px solid #aaaaaa; margin: 0; padding: 0; } thead { border: 1px solid black; } thead tr { margin: 0; padding: 0; } thead th { border-right: 1px dashed black; margin: 0; text-align: center; font-weight: bold; padding-left: .5em; padding-right: .5em; } thead th.empty { border-right: 0; } td { margin: 0; padding-left: .5em; padding-right: .5em; } tbody td { border: 1px dashed black; vertical-align: base-line; color: black; background: transparent; } tbody td.empty { color: black; background: #f5f5f5; border: 0; } tbody td.no-content { border-bottom: 1px dashed black; } tfoot td { color: black; background: #f5f5f5; border-right: 1px dashed black; } .int, .bytes, .duration, .email, .timestamp { text-align: right; } .filename, .string, .url, .int, .bytes, .duration, .email, .timestamp { font-family: courier new, courier, fixed, mono; } #toc-button, #next-button, #prev-button { position: absolute; border: 0; width: 24px; height: 24px; } #prev-button { left: 30px; } #next-button { left: 54px; } �������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/html/toc.png���������������������������������������������������������������������0000644�0001750�0001750�00000000403�10460672576�013156� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR���������w=���gAMA�� a���bKGD������ pHYs�� �� ����tIME : o?���tEXtComment�Created with The GIMPd%n���WIDATx^1 0 t%:1\'k3%# Ӎ''rKxe&Dh&jD-emy)5~Oe����IENDB`�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/html/Makefile.am�����������������������������������������������������������������0000644�0001750�0001750�00000002206�10050263146�013702� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.3 2004/05/11 23:48:54 wsourdeau Exp $ ## Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. htmldir = $(datadir)/$(PACKAGE)/html html_DATA = lire-html.css lire.png prev.png toc.png next.png EXTRA_DIST = $(html_DATA) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/html/Makefile.in�����������������������������������������������������������������0000644�0001750�0001750�00000025431�11677606132�013734� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = all/lib/html DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(htmldir)" DATA = $(html_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = $(datadir)/$(PACKAGE)/html includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ html_DATA = lire-html.css lire.png prev.png toc.png next.png EXTRA_DIST = $(html_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/html/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/html/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-htmlDATA: $(html_DATA) @$(NORMAL_INSTALL) test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)" @list='$(html_DATA)'; test -n "$(htmldir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \ done uninstall-htmlDATA: @$(NORMAL_UNINSTALL) @list='$(html_DATA)'; test -n "$(htmldir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(htmldir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(htmldir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(htmldir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-htmlDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-htmlDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-htmlDATA install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ uninstall-am uninstall-htmlDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/html/prev.png��������������������������������������������������������������������0000644�0001750�0001750�00000000470�10460672576�013351� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR���������w=���gAMA�� a���bKGD������ pHYs�� �� ����tIME :���tEXtComment�Created with The GIMPd%n���IDATx^K D'/n f>p7J��  "Vh rVdX0XNCZnz{gz r. tEWc* S%)OVP G[PO: kĚV����IENDB`��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/html/next.png��������������������������������������������������������������������0000644�0001750�0001750�00000000470�10460672576�013353� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR���������w=���gAMA�� a���bKGD������ pHYs�� �� ����tIME 98fW���tEXtComment�Created with The GIMPd%n���IDATx^K D'э."ɪ}n&� 9q-G)%-򂣄cbDP-�$YX$]A-NOEГlTIιZQoDCa)ZyM ,RN)xh&e^\skĦy����IENDB`��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Firewall/������������������������������������������������������������������������0000755�0001750�0001750�00000000000�11677607770�012554� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Firewall/Makefile.am�������������������������������������������������������������0000644�0001750�0001750�00000002367�10027406037�014515� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.1 2004/03/21 21:41:51 vanbaal Exp $ ## Copyright (C) 2004 Stichting LogReport Foundation LogReport@LogReport.org ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see COPYING); if not, check with ## http://www.gnu.org/copyleft/gpl.html or write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. include $(top_srcdir)/include/rules.mk fwperllibdir = $(LR_PERL5LIBDIR)/Lire fwperllib_DATA = Firewall.pm perlpackage = Lire man_MANS = Firewall.3pm transform = s,^,$(perlpackage)::, EXTRA_DIST = $(fwperllib_DATA) CLEANFILES = $(man_MANS) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/Firewall/Makefile.in�������������������������������������������������������������0000644�0001750�0001750�00000042716�11677606132�014542� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/include/rules.mk subdir = all/lib/Firewall ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(fwperllibdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(fwperllib_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) transform = s,^,$(perlpackage)::, ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAX_JADE_ERRORS = 10 convertorsdir = $(libexecdir)/$(PACKAGE)/convertors pluginsdir = $(sysconfdir)/$(PACKAGE)/plugins schemadir = $(datadir)/$(PACKAGE)/schemas templatesdir = $(datadir)/$(PACKAGE)/templates XML_DCL = $(top_srcdir)/all/lib/xml/xml.dcl SUFFIXES = .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in PERL2MAN1_RULE = \ $(POD2MAN) --section=1 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN3PM_RULE = \ $(POD2MAN) --section=3pm --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ PERL2MAN7_RULE = \ $(POD2MAN) --section=7 --center="LogReport's Lire Documentation" --release='Lire $(VERSION)' $? $@ XML2HTML_RULE = \ mysrc=`cd $(srcdir) && pwd`; \ mytop=`cd $(top_srcdir) && pwd`; \ outdir=`dirname $@`; \ src=$$mysrc/`basename $<`; \ $(mkinstalldirs) $$outdir && \ cd $$outdir && \ rm -f *.htm* && \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ for i in $$epss; do \ png=`basename $$i .eps`.png; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=576,576 pngalpha $$i $$png; \ done; \ XML_CATALOG_FILES=$$mytop/catalog.xml $(XSLTPROC) --nonet --param 'graphic.default.extension' '"png"' $(DBKXSLHTML) $$src HTML2TXT_RULE = \ XML_CATALOG_FILES=$(top_srcdir)/catalog.xml $(XSLTPROC) --nonet $(DBKXSLHTMLNOCHUNK) $< > tmp.html && \ $(LYNX) -nolist -dump tmp.html > $@ && \ rm tmp.html XML2PDF_RULE = \ base=`basename $@ .pdf`; \ epss=`for i in $^; do echo $$i; done | grep '\.eps$$'`; \ pdfs=""; \ for i in $$epss; do \ pdf=`basename $$i .eps`.pdf; \ $(PERL) $(top_builddir)/all/script/lr_gsconvert --resize=396,396 pdfwrite $$i $$pdf; \ pdfs="$$pdfs $$pdf"; \ done; \ $(JADE) -E$(MAX_JADE_ERRORS) -t tex -d $(DBKDSSSLPRINT) $(XML_DCL) $< && \ i=0; \ while test $$i -lt 3; do \ if $(PDFJADETEX) -interaction=batchmode $$base.tex > /dev/null; \ then \ if grep 'undefined references\| [Rr]erun' $$base.log > /dev/null; \ then :; else break; fi; \ else \ grep '^! ' $$base.log; \ exit 1; \ fi; \ i=`expr $$i + 1`; \ done; \ rm -f $$base.log $$base.out $$base.aux $$base.tex $$pdfs DIA2EPS_RULE = \ $(DIA) --nosplash -e $@ $< DIA2PNG_RULE = \ $(DIA) --nosplash -e $@ $< PERLMODULES_INSTALL_RULE = \ @for p in $(perlmodules) ; do \ f="`echo $$p | sed -e 's|^.*/lib/||'`" ; \ d="`echo $$f | sed -e 's|\(^.*\)/.*|\1|'`" ; \ if test ! -d $(DESTDIR)$(LR_PERL5LIBDIR)/$$d; then \ $(mkinstalldirs) $(DESTDIR)$(LR_PERL5LIBDIR)/$$d ; \ fi ; \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(LR_PERL5LIBDIR)/$$f ; \ done PERLMODULES_UNINSTALL_RULE = \ @for p in $(perlmodules); do \ f="`echo $$p | sed -e 's|^.*/lib/||'`"; \ echo " rm -f $(DESTDIR)$(LR_PERL5LIBDIR)/$$f"; \ rm -f $(DESTDIR)$(DESTDIR)$(LR_PERL5LIBDIR)/$$f; \ done fwperllibdir = $(LR_PERL5LIBDIR)/Lire fwperllib_DATA = Firewall.pm perlpackage = Lire man_MANS = Firewall.3pm EXTRA_DIST = $(fwperllib_DATA) CLEANFILES = $(man_MANS) all: all-am .SUFFIXES: .SUFFIXES: .pod .1 .7 .pm .3pm .dbx .xml .dia .eps .in .png $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/include/rules.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/Firewall/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/Firewall/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man3: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" @list=''; test -n "$(man3dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } install-fwperllibDATA: $(fwperllib_DATA) @$(NORMAL_INSTALL) test -z "$(fwperllibdir)" || $(MKDIR_P) "$(DESTDIR)$(fwperllibdir)" @list='$(fwperllib_DATA)'; test -n "$(fwperllibdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(fwperllibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(fwperllibdir)" || exit $$?; \ done uninstall-fwperllibDATA: @$(NORMAL_UNINSTALL) @list='$(fwperllib_DATA)'; test -n "$(fwperllibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(fwperllibdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(fwperllibdir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(fwperllibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-fwperllibDATA install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man3 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-fwperllibDATA uninstall-man uninstall-man: uninstall-man3 .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ distclean distclean-generic distdir dvi dvi-am html html-am \ info info-am install install-am install-data install-data-am \ install-dvi install-dvi-am install-exec install-exec-am \ install-fwperllibDATA install-html install-html-am \ install-info install-info-am install-man install-man3 \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-fwperllibDATA uninstall-man uninstall-man3 .pm.3pm: $(PERL2MAN3PM_RULE) .pod.1: $(PERL2MAN1_RULE) .pod.7: $(PERL2MAN7_RULE) .in.1: $(PERL2MAN1_RULE) .dia.eps: $(DIA2EPS_RULE) .dia.png: $(DIA2PNG_RULE) check-local: check-xml # We have to work with the fact that xmllint doesn't # give an error when validation fails. It exits with # non-zero status only when the file isn't well-formed # We have to test for either srcdir/$f or $f : lire.xml # exists in . only. # check-xml: $(XML_FILES) @if test -z "$(XML_FILES)"; \ then \ echo No XML files to validate; \ else \ for f in $(XML_FILES); \ do \ echo -n Checking $$f...; \ test -f $(srcdir)/$$f && file=$(srcdir)/$$f || file=$$f; \ SGML_CATALOG_FILES="$(top_builddir)/catalog:$(top_srcdir)/all/lib/xml/dtd/catalog" $(XMLLINT) --catalogs --noout --valid $$file 2> xmllint.error; \ if test -s xmllint.error; \ then \ echo failed; \ cat xmllint.error; \ rm -f xmllint.error; \ exit 1; \ else \ echo ok; \ rm -f xmllint.error; \ fi; \ done; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ��������������������������������������������������lire-2.1.1/all/lib/Firewall/Firewall.pm�������������������������������������������������������������0000644�0001750�0001750�00000165570�10460673253�014601� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Lire::Firewall; use strict; use vars qw/ @ISA @EXPORT_OK %EXPORT_TAGS/; # use Lire::Utils host_by_addr BEGIN { require Exporter; @ISA = qw/ Exporter /; @EXPORT_OK = qw/firewall_number2names firewall_resolve/; %EXPORT_TAGS = ( 'num2name' => [qw/ num2proto num2tcp_serv num2udp_serv num2icmp_type/ ], ); foreach my $tag ( keys %EXPORT_TAGS ) { Exporter::export_ok_tags( $tag ); } } sub firewall_resolve { my ( $dlf ) = $_[0]; my $host; unless( defined $dlf->{'to_host'} ) { $host = host_by_addr( $dlf->{'to_ip'} ); defined $host and $dlf->{'to_host'} = $host; } unless( defined $dlf->{'from_host'} ) { $host = host_by_addr( $dlf->{'from_ip'} ); defined $host and $dlf->{'from_host'} = $host; } $dlf; } sub firewall_number2names { my ( $dlf ) = $_[0]; return $dlf unless defined $dlf->{'protocol'}; if ( $dlf->{'protocol'} =~ /\d+/ ) { $dlf->{'protocol'} = num2proto( $dlf->{'protocol'} ); } else { $dlf->{'protocol'} = lc $dlf->{'protocol'}; } # Normalize the names if ( $dlf->{'protocol'} eq 'tcp' ) { $dlf->{'to_port'} = num2tcp_serv( $dlf->{'to_port'} ); } elsif ( $dlf->{'protocol'} eq 'udp' ) { $dlf->{'to_port'} = num2udp_serv( $dlf->{'to_port'} ); } elsif ( $dlf->{'protocol'} eq 'icmp' ) { $dlf->{'from_port'} = num2icmp_type( $dlf->{'from_port'} ); } $dlf; } my %num2proto = ( # # Generated by running # perl -ane 'next if /^\s*(#|\s*$)/; # print " ", $F[1], " => \"", $F[0], "\",\n"' /usr/share/nmap/nmap-protocols '0' => "hopopt", '1' => "icmp", '2' => "igmp", '3' => "ggp", '4' => "ip", '5' => "st", '6' => "tcp", '7' => "cbt", '8' => "egp", '9' => "igp", '10' => "bbn-rcc-mon", '11' => "nvp-ii", '12' => "pup", '13' => "argus", '14' => "emcon", '15' => "xnet", '16' => "chaos", '17' => "udp", '18' => "mux", '19' => "dcn-meas", '20' => "hmp", '21' => "prm", '22' => "xns-idp", '23' => "trunk-1", '24' => "trunk-2", '25' => "leaf-1", '26' => "leaf-2", '27' => "rdp", '28' => "irtp", '29' => "iso-tp4", '30' => "netblt", '31' => "mfe-nsp", '32' => "merit-inp", '33' => "sep", '34' => "3pc", '35' => "idpr", '36' => "xtp", '37' => "ddp", '38' => "idpr-cmtp", '39' => "tp++", '40' => "il", '41' => "ipv6", '42' => "sdrp", '43' => "ipv6-route", '44' => "ipv6-frag", '45' => "idrp", '46' => "rsvp", '47' => "gre", '48' => "mhrp", '49' => "bna", '50' => "esp", '51' => "ah", '52' => "i-nlsp", '53' => "swipe", '54' => "narp", '55' => "mobile", '56' => "tlsp", '57' => "skip", '58' => "ipv6-icmp", '59' => "ipv6-nonxt", '60' => "ipv6-opts", '62' => "cftp", '64' => "sat-expak", '65' => "kryptolan", '66' => "rvd", '67' => "ippc", '69' => "sat-mon", '70' => "visa", '71' => "ipcv", '72' => "cpnx", '73' => "cphb", '74' => "wsn", '75' => "pvp", '76' => "br-sat-mon", '77' => "sun-nd", '78' => "wb-mon", '79' => "wb-expak", '80' => "iso-ip", '81' => "vmtp", '82' => "secure-vmtp", '83' => "vines", '84' => "ttp", '85' => "nsfnet-igp", '86' => "dgp", '87' => "tcf", '88' => "eigrp", '89' => "ospfigp", '90' => "sprite-rpc", '91' => "larp", '92' => "mtp", '93' => "ax.25", '94' => "ipip", '95' => "micp", '96' => "scc-SP", '97' => "etherip", '98' => "encap", '100' => "gmtp", '101' => "ifmp", '102' => "pnni", '103' => "pim", '104' => "aris", '105' => "scps", '106' => "qnx", '107' => "a/n", '108' => "ipcomp", '109' => "snp", '110' => "compaq-peer", '111' => "ipx-in-ip", '112' => "vrrp", '113' => "pgm", '115' => "l2tp", '116' => "ddx", '117' => "iatp", '118' => "stp", '119' => "srp", '120' => "uti", '121' => "smp", '122' => "sm", '123' => "ptp", '124' => "isis-over-ipv4", '125' => "fire", '126' => "crtp", '127' => "crudp", '128' => "sscopmce", '129' => "iplt", '130' => "sps", '131' => "pipe", '132' => "sctp", '133' => "fc", ); sub num2proto { return undef unless defined $_[0]; my $name = $num2proto{$_[0]}; defined $name ? $name : $_[0]; } # perl -ane 'BEGIN { $the_proto = shift; } # next if /^\s*(#|\s*$)/; # my ( $port, $proto ) = $F[1] =~ m,(\d+)/(\w+),; # next unless $proto eq $the_proto; # print " ", $port, " => \"", $F[0], "\",\n"' tcp /usr/share/nmap/nmap-services my %num2tcp_serv = ( '1' => "tcpmux", '2' => "compressnet", '3' => "compressnet", '5' => "rje", '7' => "echo", '9' => "discard", '11' => "systat", '13' => "daytime", '15' => "netstat", '17' => "qotd", '18' => "msp", '19' => "chargen", '20' => "ftp-data", '21' => "ftp", '22' => "ssh", '23' => "telnet", '24' => "priv-mail", '25' => "smtp", '27' => "nsw-fe", '29' => "msg-icp", '31' => "msg-auth", '33' => "dsp", '35' => "priv-print", '37' => "time", '38' => "rap", '39' => "rlp", '41' => "graphics", '42' => "nameserver", '43' => "whois", '44' => "mpm-flags", '45' => "mpm", '46' => "mpm-snd", '47' => "ni-ftp", '48' => "auditd", '49' => "tacacs", '50' => "re-mail-ck", '51' => "la-maint", '52' => "xns-time", '53' => "domain", '54' => "xns-ch", '55' => "isi-gl", '56' => "xns-auth", '57' => "priv-term", '58' => "xns-mail", '59' => "priv-file", '61' => "ni-mail", '62' => "acas", '63' => "via-ftp", '64' => "covia", '65' => "tacacs-ds", '66' => "sql*net", '67' => "bootps", '68' => "bootpc", '69' => "tftp", '70' => "gopher", '71' => "netrjs-1", '72' => "netrjs-2", '73' => "netrjs-3", '74' => "netrjs-4", '75' => "priv-dial", '76' => "deos", '77' => "priv-rje", '78' => "vettcp", '79' => "finger", '80' => "http", '81' => "hosts2-ns", '82' => "xfer", '83' => "mit-ml-dev", '84' => "ctf", '85' => "mit-ml-dev", '86' => "mfcobol", '87' => "priv-term-l", '88' => "kerberos-sec", '89' => "su-mit-tg", '90' => "dnsix", '91' => "mit-dov", '92' => "npp", '93' => "dcp", '94' => "objcall", '95' => "supdup", '96' => "dixie", '97' => "swift-rvf", '98' => "linuxconf", '99' => "metagram", '100' => "newacct", '101' => "hostname", '102' => "iso-tsap", '103' => "gppitnp", '104' => "acr-nema", '105' => "csnet-ns", '106' => "pop3pw", '107' => "rtelnet", '108' => "snagas", '109' => "pop-2", '110' => "pop-3", '111' => "sunrpc", '112' => "mcidas", '113' => "auth", '114' => "audionews", '115' => "sftp", '116' => "ansanotify", '117' => "uucp-path", '118' => "sqlserv", '119' => "nntp", '120' => "cfdptkt", '121' => "erpc", '122' => "smakynet", '123' => "ntp", '124' => "ansatrader", '125' => "locus-map", '126' => "unitary", '127' => "locus-con", '128' => "gss-xlicen", '129' => "pwdgen", '130' => "cisco-fna", '131' => "cisco-tna", '132' => "cisco-sys", '133' => "statsrv", '134' => "ingres-net", '135' => "loc-srv", '136' => "profile", '137' => "netbios-ns", '138' => "netbios-dgm", '139' => "netbios-ssn", '140' => "emfis-data", '141' => "emfis-cntl", '142' => "bl-idm", '143' => "imap2", '144' => "news", '145' => "uaac", '146' => "iso-tp0", '147' => "iso-ip", '148' => "cronus", '149' => "aed-512", '150' => "sql-net", '151' => "hems", '152' => "bftp", '153' => "sgmp", '154' => "netsc-prod", '155' => "netsc-dev", '156' => "sqlsrv", '157' => "knet-cmp", '158' => "pcmail-srv", '159' => "nss-routing", '160' => "sgmp-traps", '161' => "snmp", '162' => "snmptrap", '163' => "cmip-man", '164' => "cmip-agent", '165' => "xns-courier", '166' => "s-net", '167' => "namp", '168' => "rsvd", '169' => "send", '170' => "print-srv", '171' => "multiplex", '172' => "cl-1", '173' => "xyplex-mux", '174' => "mailq", '175' => "vmnet", '176' => "genrad-mux", '177' => "xdmcp", '178' => "nextstep", '179' => "bgp", '180' => "ris", '181' => "unify", '182' => "audit", '183' => "ocbinder", '184' => "ocserver", '185' => "remote-kis", '186' => "kis", '187' => "aci", '188' => "mumps", '189' => "qft", '190' => "gacp", '191' => "prospero", '192' => "osu-nms", '193' => "srmp", '194' => "irc", '195' => "dn6-nlm-aud", '196' => "dn6-smm-red", '197' => "dls", '198' => "dls-mon", '199' => "smux", '200' => "src", '201' => "at-rtmp", '202' => "at-nbp", '203' => "at-3", '204' => "at-echo", '205' => "at-5", '206' => "at-zis", '207' => "at-7", '208' => "at-8", '209' => "tam", '210' => "z39.50", '211' => "914c-g", '212' => "anet", '213' => "ipx", '214' => "vmpwscs", '215' => "softpc", '216' => "atls", '217' => "dbase", '218' => "mpp", '219' => "uarps", '220' => "imap3", '221' => "fln-spx", '222' => "rsh-spx", '223' => "cdc", '242' => "direct", '243' => "sur-meas", '244' => "dayna", '245' => "link", '246' => "dsp3270", '247' => "subntbcst_tftp", '248' => "bhfhs", '256' => "rap", '257' => "set", '258' => "yak-chat", '259' => "esro-gen", '260' => "openport", '261' => "nsiiops", '262' => "arcisdms", '263' => "hdap", '264' => "bgmp", '280' => "http-mgmt", '281' => "personal-link", '282' => "cableport-ax", '308' => "novastorbakcup", '309' => "entrusttime", '310' => "bhmds", '311' => "asip-webadmin", '312' => "vslmp", '313' => "magenta-logic", '314' => "opalis-robot", '315' => "dpsi", '316' => "decauth", '317' => "zannet", '321' => "pip", '344' => "pdap", '345' => "pawserv", '346' => "zserv", '347' => "fatserv", '348' => "csi-sgwp", '349' => "mftp", '350' => "matip-type-a", '351' => "matip-type-b", '352' => "dtag-ste-sb", '353' => "ndsauth", '354' => "bh611", '355' => "datex-asn", '356' => "cloanto-net-1", '357' => "bhevent", '358' => "shrinkwrap", '359' => "tenebris_nts", '360' => "scoi2odialog", '361' => "semantix", '362' => "srssend", '363' => "rsvp_tunnel", '364' => "aurora-cmgr", '365' => "dtk", '366' => "odmr", '367' => "mortgageware", '368' => "qbikgdp", '369' => "rpc2portmap", '370' => "codaauth2", '371' => "clearcase", '372' => "ulistserv", '373' => "legent-1", '374' => "legent-2", '375' => "hassle", '376' => "nip", '377' => "tnETOS", '378' => "dsETOS", '379' => "is99c", '380' => "is99s", '381' => "hp-collector", '382' => "hp-managed-node", '383' => "hp-alarm-mgr", '384' => "arns", '385' => "ibm-app", '386' => "asa", '387' => "aurp", '388' => "unidata-ldm", '389' => "ldap", '390' => "uis", '391' => "synotics-relay", '392' => "synotics-broker", '393' => "dis", '394' => "embl-ndt", '395' => "netcp", '396' => "netware-ip", '397' => "mptn", '398' => "kryptolan", '399' => "iso-tsap-c2", '400' => "work-sol", '401' => "ups", '402' => "genie", '403' => "decap", '404' => "nced", '405' => "ncld", '406' => "imsp", '407' => "timbuktu", '408' => "prm-sm", '409' => "prm-nm", '410' => "decladebug", '411' => "rmt", '412' => "synoptics-trap", '413' => "smsp", '414' => "infoseek", '415' => "bnet", '416' => "silverplatter", '417' => "onmux", '418' => "hyper-g", '419' => "ariel1", '420' => "smpte", '421' => "ariel2", '422' => "ariel3", '423' => "opc-job-start", '424' => "opc-job-track", '425' => "icad-el", '426' => "smartsdp", '427' => "svrloc", '428' => "ocs_cmu", '429' => "ocs_amu", '430' => "utmpsd", '431' => "utmpcd", '432' => "iasd", '433' => "nnsp", '434' => "mobileip-agent", '435' => "mobilip-mn", '436' => "dna-cml", '437' => "comscm", '438' => "dsfgw", '439' => "dasp", '440' => "sgcp", '441' => "decvms-sysmgt", '442' => "cvc_hostd", '443' => "https", '444' => "snpp", '445' => "microsoft-ds", '446' => "ddm-rdb", '447' => "ddm-dfm", '448' => "ddm-ssl", '449' => "as-servermap", '450' => "tserver", '451' => "sfs-smp-net", '452' => "sfs-config", '453' => "creativeserver", '454' => "contentserver", '455' => "creativepartnr", '456' => "macon-tcp", '457' => "scohelp", '458' => "appleqtc", '459' => "ampr-rcmd", '460' => "skronk", '461' => "datasurfsrv", '462' => "datasurfsrvsec", '463' => "alpes", '464' => "kpasswd5", '465' => "smtps", '466' => "digital-vrc", '467' => "mylex-mapd", '468' => "photuris", '469' => "rcp", '470' => "scx-proxy", '471' => "mondex", '472' => "ljk-login", '473' => "hybrid-pop", '474' => "tn-tl-w1", '475' => "tcpnethaspsrv", '476' => "tn-tl-fd1", '477' => "ss7ns", '478' => "spsc", '479' => "iafserver", '480' => "loadsrv", '481' => "dvs", '482' => "bgs-nsi", '483' => "ulpnet", '484' => "integra-sme", '485' => "powerburst", '486' => "sstats", '487' => "saft", '488' => "gss-http", '489' => "nest-protocol", '490' => "micom-pfs", '491' => "go-login", '492' => "ticf-1", '493' => "ticf-2", '494' => "pov-ray", '495' => "intecourier", '496' => "pim-rp-disc", '497' => "dantz", '498' => "siam", '499' => "iso-ill", '500' => "isakmp", '501' => "stmf", '502' => "asa-appl-proto", '503' => "intrinsa", '504' => "citadel", '505' => "mailbox-lm", '506' => "ohimsrv", '507' => "crs", '508' => "xvttp", '509' => "snare", '510' => "fcp", '511' => "passgo", '512' => "exec", '513' => "login", '514' => "shell", '515' => "printer", '516' => "videotex", '517' => "talk", '518' => "ntalk", '519' => "utime", '520' => "efs", '521' => "ripng", '522' => "ulp", '523' => "ibm-db2", '524' => "ncp", '525' => "timed", '526' => "tempo", '527' => "stx", '528' => "custix", '529' => "irc-serv", '530' => "courier", '531' => "conference", '532' => "netnews", '533' => "netwall", '534' => "mm-admin", '535' => "iiop", '536' => "opalis-rdv", '537' => "nmsp", '538' => "gdomap", '539' => "apertus-ldp", '540' => "uucp", '541' => "uucp-rlogin", '542' => "commerce", '543' => "klogin", '544' => "kshell", '545' => "ekshell", '546' => "dhcpv6-client", '547' => "dhcpv6-server", '548' => "afpovertcp", '549' => "idfp", '550' => "new-rwho", '551' => "cybercash", '552' => "deviceshare", '553' => "pirp", '554' => "rtsp", '555' => "dsf", '556' => "remotefs", '557' => "openvms-sysipc", '558' => "sdnskmp", '559' => "teedtap", '560' => "rmonitor", '561' => "monitor", '562' => "chshell", '563' => "snews", '564' => "9pfs", '565' => "whoami", '566' => "streettalk", '567' => "banyan-rpc", '568' => "ms-shuttle", '569' => "ms-rome", '570' => "meter", '571' => "umeter", '572' => "sonar", '573' => "banyan-vip", '574' => "ftp-agent", '575' => "vemmi", '576' => "ipcd", '577' => "vnas", '578' => "ipdd", '579' => "decbsrv", '580' => "sntp-heartbeat", '581' => "bdp", '582' => "scc-security", '583' => "philips-vc", '584' => "keyserver", '585' => "imap4-ssl", '586' => "password-chg", '587' => "submission", '588' => "cal", '589' => "eyelink", '590' => "tns-cml", '591' => "http-alt", '592' => "eudora-set", '593' => "http-rpc-epmap", '594' => "tpip", '595' => "cab-protocol", '596' => "smsd", '597' => "ptcnameservice", '598' => "sco-websrvrmg3", '599' => "acp", '600' => "ipcserver", '606' => "urm", '607' => "nqs", '608' => "sift-uft", '609' => "npmp-trap", '610' => "npmp-local", '611' => "npmp-gui", '628' => "qmqp", '631' => "cups", '634' => "ginad", '636' => "ldapssl", '666' => "doom", '691' => "resvc", '704' => "elcsd", '709' => "entrustmanager", '729' => "netviewdm1", '730' => "netviewdm2", '731' => "netviewdm3", '740' => "netcp", '741' => "netgw", '742' => "netrcs", '744' => "flexlm", '747' => "fujitsu-dev", '748' => "ris-cm", '749' => "kerberos-adm", '750' => "kerberos", '751' => "kerberos_master", '752' => "qrh", '753' => "rrh", '754' => "krb_prop", '758' => "nlogin", '759' => "con", '760' => "krbupdate", '761' => "kpasswd", '762' => "quotad", '763' => "cycleserv", '764' => "omserv", '765' => "webster", '767' => "phonebook", '769' => "vid", '770' => "cadlock", '771' => "rtip", '772' => "cycleserv2", '773' => "submit", '774' => "rpasswd", '775' => "entomb", '776' => "wpages", '780' => "wpgs", '781' => "hp-collector", '782' => "hp-managed-node", '783' => "hp-alarm-mgr", '786' => "concert", '799' => "controlit", '800' => "mdbs_daemon", '801' => "device", '871' => "supfilesrv", '873' => "rsync", '888' => "accessbuilder", '989' => "ftps-data", '901' => "samba-swat", '950' => "oftep-rpc", '953' => "rndc", '975' => "securenetpro-sensor", '990' => "ftps", '992' => "telnets", '993' => "imaps", '994' => "ircs", '995' => "pop3s", '996' => "xtreelic", '997' => "maitrd", '998' => "busboy", '999' => "garcon", '1000' => "cadlock", '1008' => "ufsd", '1024' => "kdm", '1025' => "listen", '1026' => "nterm", '1030' => "iad1", '1031' => "iad2", '1032' => "iad3", '1058' => "nim", '1059' => "nimreg", '1067' => "instl_boots", '1068' => "instl_bootc", '1080' => "socks", '1083' => "ansoft-lm-1", '1084' => "ansoft-lm-2", '1103' => "xaudio", '1109' => "kpop", '1110' => "nfsd-status", '1112' => "msql", '1127' => "supfiledbg", '1139' => "cce3x", '1155' => "nfa", '1178' => "skkserv", '1212' => "lupa", '1222' => "nerv", '1234' => "hotline", '1241' => "msg", '1248' => "hermes", '1346' => "alta-ana-lm", '1347' => "bbn-mmc", '1348' => "bbn-mmx", '1349' => "sbook", '1350' => "editbench", '1351' => "equationbuilder", '1352' => "lotusnotes", '1353' => "relief", '1354' => "rightbrain", '1355' => "intuitive-edge", '1356' => "cuillamartin", '1357' => "pegboard", '1358' => "connlcli", '1359' => "ftsrv", '1360' => "mimer", '1361' => "linx", '1362' => "timeflies", '1363' => "ndm-requester", '1364' => "ndm-server", '1365' => "adapt-sna", '1366' => "netware-csp", '1367' => "dcs", '1368' => "screencast", '1369' => "gv-us", '1370' => "us-gv", '1371' => "fc-cli", '1372' => "fc-ser", '1373' => "chromagrafx", '1374' => "molly", '1375' => "bytex", '1376' => "ibm-pps", '1377' => "cichlid", '1378' => "elan", '1379' => "dbreporter", '1380' => "telesis-licman", '1381' => "apple-licman", '1383' => "gwha", '1384' => "os-licman", '1385' => "atex_elmd", '1386' => "checksum", '1387' => "cadsi-lm", '1388' => "objective-dbc", '1389' => "iclpv-dm", '1390' => "iclpv-sc", '1391' => "iclpv-sas", '1392' => "iclpv-pm", '1393' => "iclpv-nls", '1394' => "iclpv-nlc", '1395' => "iclpv-wsm", '1396' => "dvl-activemail", '1397' => "audio-activmail", '1398' => "video-activmail", '1399' => "cadkey-licman", '1400' => "cadkey-tablet", '1401' => "goldleaf-licman", '1402' => "prm-sm-np", '1403' => "prm-nm-np", '1404' => "igi-lm", '1405' => "ibm-res", '1406' => "netlabs-lm", '1407' => "dbsa-lm", '1408' => "sophia-lm", '1409' => "here-lm", '1410' => "hiq", '1411' => "af", '1412' => "innosys", '1413' => "innosys-acl", '1414' => "ibm-mqseries", '1415' => "dbstar", '1416' => "novell-lu6.2", '1417' => "timbuktu-srv1", '1418' => "timbuktu-srv2", '1419' => "timbuktu-srv3", '1420' => "timbuktu-srv4", '1421' => "gandalf-lm", '1422' => "autodesk-lm", '1423' => "essbase", '1424' => "hybrid", '1425' => "zion-lm", '1426' => "sas-1", '1427' => "mloadd", '1428' => "informatik-lm", '1429' => "nms", '1430' => "tpdu", '1431' => "rgtp", '1432' => "blueberry-lm", '1433' => "ms-sql-s", '1434' => "ms-sql-m", '1435' => "ibm-cics", '1436' => "sas-2", '1437' => "tabula", '1438' => "eicon-server", '1439' => "eicon-x25", '1440' => "eicon-slp", '1441' => "cadis-1", '1442' => "cadis-2", '1443' => "ies-lm", '1444' => "marcam-lm", '1445' => "proxima-lm", '1446' => "ora-lm", '1447' => "apri-lm", '1448' => "oc-lm", '1449' => "peport", '1450' => "dwf", '1451' => "infoman", '1452' => "gtegsc-lm", '1453' => "genie-lm", '1454' => "interhdl_elmd", '1455' => "esl-lm", '1456' => "dca", '1457' => "valisys-lm", '1458' => "nrcabq-lm", '1459' => "proshare1", '1460' => "proshare2", '1461' => "ibm_wrless_lan", '1462' => "world-lm", '1463' => "nucleus", '1464' => "msl_lmd", '1465' => "pipes", '1466' => "oceansoft-lm", '1467' => "csdmbase", '1468' => "csdm", '1469' => "aal-lm", '1470' => "uaiact", '1471' => "csdmbase", '1472' => "csdm", '1473' => "openmath", '1474' => "telefinder", '1475' => "taligent-lm", '1476' => "clvm-cfg", '1477' => "ms-sna-server", '1478' => "ms-sna-base", '1479' => "dberegister", '1480' => "pacerforum", '1481' => "airs", '1482' => "miteksys-lm", '1483' => "afs", '1484' => "confluent", '1485' => "lansource", '1486' => "nms_topo_serv", '1487' => "localinfosrvr", '1488' => "docstor", '1489' => "dmdocbroker", '1490' => "insitu-conf", '1491' => "anynetgateway", '1492' => "stone-design-1", '1493' => "netmap_lm", '1494' => "citrix-ica", '1495' => "cvc", '1496' => "liberty-lm", '1497' => "rfx-lm", '1498' => "watcom-sql", '1499' => "fhc", '1500' => "vlsi-lm", '1501' => "sas-3", '1502' => "shivadiscovery", '1503' => "imtc-mcs", '1504' => "evb-elm", '1505' => "funkproxy", '1506' => "utcd", '1507' => "symplex", '1508' => "diagmond", '1509' => "robcad-lm", '1510' => "mvx-lm", '1511' => "3l-l1", '1512' => "wins", '1513' => "fujitsu-dtc", '1514' => "fujitsu-dtcns", '1515' => "ifor-protocol", '1516' => "vpad", '1517' => "vpac", '1518' => "vpvd", '1519' => "vpvc", '1520' => "atm-zip-office", '1521' => "oracle", '1522' => "rna-lm", '1523' => "cichild-lm", '1524' => "ingreslock", '1525' => "orasrv", '1526' => "pdap-np", '1527' => "tlisrv", '1528' => "mciautoreg", '1529' => "support", '1530' => "rap-service", '1531' => "rap-listen", '1532' => "miroconnect", '1533' => "virtual-places", '1534' => "micromuse-lm", '1535' => "ampr-info", '1536' => "ampr-inter", '1537' => "sdsc-lm", '1538' => "3ds-lm", '1539' => "intellistor-lm", '1540' => "rds", '1541' => "rds2", '1542' => "gridgen-elmd", '1543' => "simba-cs", '1544' => "aspeclmd", '1545' => "vistium-share", '1546' => "abbaccuray", '1547' => "laplink", '1548' => "axon-lm", '1549' => "shivahose", '1550' => "3m-image-lm", '1551' => "hecmtl-db", '1552' => "pciarray", '1600' => "issd", '1650' => "nkd", '1651' => "shiva_confsrvr", '1652' => "xnmp", '1661' => "netview-aix-1", '1662' => "netview-aix-2", '1663' => "netview-aix-3", '1664' => "netview-aix-4", '1665' => "netview-aix-5", '1666' => "netview-aix-6", '1667' => "netview-aix-7", '1668' => "netview-aix-8", '1669' => "netview-aix-9", '1670' => "netview-aix-10", '1671' => "netview-aix-11", '1672' => "netview-aix-12", '1723' => "pptp", '1827' => "pcm", '1986' => "licensedaemon", '1987' => "tr-rsrb-p1", '1988' => "tr-rsrb-p2", '1989' => "tr-rsrb-p3", '1990' => "stun-p1", '1991' => "stun-p2", '1992' => "stun-p3", '1993' => "snmp-tcp-port", '1994' => "stun-port", '1995' => "perf-port", '1996' => "tr-rsrb-port", '1997' => "gdp-port", '1998' => "x25-svc-port", '1999' => "tcp-id-port", '2000' => "callbook", '2001' => "dc", '2002' => "globe", '2003' => "cfingerd", '2004' => "mailbox", '2005' => "deslogin", '2006' => "invokator", '2007' => "dectalk", '2008' => "conf", '2009' => "news", '2010' => "search", '2011' => "raid-cc", '2012' => "ttyinfo", '2013' => "raid-am", '2014' => "troff", '2015' => "cypress", '2016' => "bootserver", '2017' => "cypress-stat", '2018' => "terminaldb", '2019' => "whosockami", '2020' => "xinupageserver", '2021' => "servexec", '2022' => "down", '2023' => "xinuexpansion3", '2024' => "xinuexpansion4", '2025' => "ellpack", '2026' => "scrabble", '2027' => "shadowserver", '2028' => "submitserver", '2030' => "device2", '2032' => "blackboard", '2033' => "glogger", '2034' => "scoremgr", '2035' => "imsldoc", '2038' => "objectmanager", '2040' => "lam", '2041' => "interbase", '2042' => "isis", '2043' => "isis-bcast", '2044' => "rimsl", '2045' => "cdfunc", '2046' => "sdfunc", '2047' => "dls", '2048' => "dls-monitor", '2049' => "nfs", '2064' => "distrib-net-losers", '2065' => "dlsrpn", '2067' => "dlswpn", '2105' => "eklogin", '2106' => "ekshell", '2108' => "rkinit", '2111' => "kx", '2112' => "kip", '2120' => "kauth", '2201' => "ats", '2232' => "ivs-video", '2241' => "ivsd", '2301' => "compaqdiag", '2307' => "pehelp", '2401' => "cvspserver", '2430' => "venus", '2431' => "venus-se", '2432' => "codasrv", '2433' => "codasrv-se", '2500' => "rtsserv", '2501' => "rtsclient", '2564' => "hp-3000-telnet", '2600' => "zebrasrv", '2601' => "zebra", '2602' => "ripd", '2603' => "ripngd", '2604' => "ospfd", '2605' => "bgpd", '2627' => "webster", '2638' => "sybase", '2766' => "listen", '2784' => "www-dev", '2998' => "iss-realsec", '3000' => "ppp", '3001' => "nessusd", '3005' => "deslogin", '3006' => "deslogind", '3049' => "cfs", '3064' => "distrib-net-proxy", '3086' => "sj3", '3128' => "squid-http", '3141' => "vmodem", '3264' => "ccmail", '3306' => "mysql", '3333' => "dec-notes", '3389' => "msrdp", '3421' => "bmap", '3455' => "prsvp", '3456' => "vat", '3457' => "vat-control", '3462' => "track", '3900' => "udt_os", '3984' => "mapper-nodemgr", '3985' => "mapper-mapethd", '3986' => "mapper-ws_ethd", '4008' => "netcheque", '4045' => "lockd", '4132' => "nuts_dem", '4133' => "nuts_bootp", '4144' => "wincim", '4321' => "rwhois", '4333' => "msql", '4343' => "unicall", '4444' => "krb524", '4500' => "sae-urn", '4557' => "fax", '4559' => "hylafax", '4672' => "rfa", '5000' => "fics", '5001' => "commplex-link", '5002' => "rfe", '5010' => "telelpathstart", '5011' => "telelpathattack", '5050' => "mmcc", '5145' => "rmonitor_secure", '5190' => "aol", '5191' => "aol-1", '5192' => "aol-2", '5193' => "aol-3", '5232' => "sgi-dgl", '5236' => "padl2sim", '5300' => "hacl-hb", '5301' => "hacl-gs", '5302' => "hacl-cfg", '5303' => "hacl-probe", '5304' => "hacl-local", '5305' => "hacl-test", '5308' => "cfengine", '5400' => "pcduo-old", '5405' => "pcduo", '5432' => "postgres", '5510' => "secureidprop", '5520' => "sdlog", '5530' => "sdserv", '5540' => "sdreport", '5550' => "sdadmind", '5631' => "pcanywheredata", '5632' => "pcanywherestat", '5680' => "canna", '5713' => "proshareaudio", '5714' => "prosharevideo", '5715' => "prosharedata", '5716' => "prosharerequest", '5717' => "prosharenotify", '5800' => "vnc", '5801' => "vnc", '5900' => "vnc", '5901' => "vnc-1", '5902' => "vnc-2", '5977' => "ncd-pref-tcp", '5978' => "ncd-diag-tcp", '5979' => "ncd-conf-tcp", '5997' => "ncd-pref", '5998' => "ncd-diag", '5999' => "ncd-conf", '6000' => "X11", '6001' => "X11:1", '6002' => "X11:2", '6003' => "X11:3", '6004' => "X11:4", '6005' => "X11:5", '6006' => "X11:6", '6007' => "X11:7", '6008' => "X11:8", '6009' => "X11:9", '6050' => "arcserve", '6105' => "isdninfo", '6106' => "isdninfo", '6110' => "softcm", '6111' => "spc", '6112' => "dtspc", '6141' => "meta-corp", '6142' => "aspentec-lm", '6143' => "watershed-lm", '6144' => "statsci1-lm", '6145' => "statsci2-lm", '6146' => "lonewolf-lm", '6147' => "montage-lm", '6148' => "ricardo-lm", '6502' => "netop-rc", '6558' => "xdsxdm", '6666' => "irc-serv", '6667' => "irc", '6668' => "irc", '6969' => "acmsoda", '6699' => "napster", '7000' => "afs3-fileserver", '7001' => "afs3-callback", '7002' => "afs3-prserver", '7003' => "afs3-vlserver", '7004' => "afs3-kaserver", '7005' => "afs3-volser", '7006' => "afs3-errors", '7007' => "afs3-bos", '7008' => "afs3-update", '7009' => "afs3-rmtsys", '7010' => "ups-onlinet", '7100' => "font-service", '7200' => "fodms", '7201' => "dlip", '7326' => "icb", '7597' => "qaz", '8007' => "jserv", '8009' => "ajp13", '8080' => "http-proxy", '8081' => "blackice-icecap", '8082' => "blackice-alerts", '8888' => "sun-answerbook", '8892' => "seosload", '9090' => "zeus-admin", '9100' => "jetdirect", '9111' => "DragonIDSConsole", '9535' => "man", '9876' => "sd", '9991' => "issa", '9992' => "issc", '10000' => "snet-sensor-mgmt", '10005' => "stel", '10082' => "amandaidx", '10083' => "amidxtape", '11371' => "pksd", '12000' => "cce4x", '12345' => "NetBus", '12346' => "NetBus", '17007' => "isode-dua", '18000' => "biimenu", '20005' => "btx", '22273' => "wnn6", '22289' => "wnn6_Cn", '22305' => "wnn6_Kr", '22321' => "wnn6_Tw", '22370' => "hpnpd", '26208' => "wnn6_DS", '27665' => "Trinoo_Master", '31337' => "Elite", '32770' => "sometimes-rpc3", '32771' => "sometimes-rpc5", '32772' => "sometimes-rpc7", '32773' => "sometimes-rpc9", '32774' => "sometimes-rpc11", '32775' => "sometimes-rpc13", '32776' => "sometimes-rpc15", '32777' => "sometimes-rpc17", '32778' => "sometimes-rpc19", '32779' => "sometimes-rpc21", '32780' => "sometimes-rpc23", '32786' => "sometimes-rpc25", '32787' => "sometimes-rpc27", '43188' => "reachout", '44442' => "coldfusion-auth", '44443' => "coldfusion-auth", '47557' => "dbbrowse", '54320' => "bo2k", '61439' => "netprowler-manager", '61440' => "netprowler-manager2", '61441' => "netprowler-sensor", '65301' => "pcanywhere", ); sub num2tcp_serv { return undef unless defined $_[0]; my $name = $num2tcp_serv{$_[0]}; defined $name ? $name : $_[0]; } # perl -ane 'BEGIN { $the_proto = shift; } # next if /^\s*(#|\s*$)/; # my ( $port, $proto ) = $F[1] =~ m,(\d+)/(\w+),; # next unless $proto eq $the_proto; # print " ", $port, " => \"", $F[0], "\",\n"' tcp /usr/share/nmap/nmap-services my %num2udp_serv = ( '1' => "tcpmux", '2' => "compressnet", '3' => "compressnet", '5' => "rje", '7' => "echo", '9' => "discard", '11' => "systat", '13' => "daytime", '17' => "qotd", '18' => "msp", '19' => "chargen", '20' => "ftp-data", '21' => "ftp", '22' => "ssh", '23' => "telnet", '24' => "priv-mail", '25' => "smtp", '27' => "nsw-fe", '29' => "msg-icp", '31' => "msg-auth", '33' => "dsp", '35' => "priv-print", '37' => "time", '38' => "rap", '39' => "rlp", '41' => "graphics", '42' => "nameserver", '43' => "shois", '44' => "mpm-flags", '45' => "mpm", '46' => "mpm-snd", '47' => "ni-ftp", '48' => "auditd", '49' => "tacacs", '50' => "re-mail-ck", '51' => "la-maint", '52' => "xns-time", '53' => "domain", '54' => "xns-ch", '55' => "isi-gl", '56' => "xns-auth", '57' => "priv-term", '58' => "xns-mail", '59' => "priv-file", '61' => "ni-mail", '62' => "acas", '63' => "via-ftp", '64' => "covia", '65' => "tacacs-ds", '66' => "sql*net", '67' => "bootps", '68' => "bootpc", '69' => "tftp", '70' => "gopher", '71' => "netrjs-1", '72' => "netrjs-2", '73' => "netrjs-3", '74' => "netrjs-4", '75' => "priv-dial", '76' => "deos", '77' => "priv-rje", '78' => "vettcp", '79' => "finger", '80' => "http", '81' => "hosts2-ns", '82' => "xfer", '83' => "mit-ml-dev", '84' => "ctf", '85' => "mit-ml-dev", '86' => "mfcobol", '88' => "kerberos-sec", '89' => "su-mit-tg", '90' => "dnsix", '91' => "mit-dov", '92' => "npp", '93' => "dcp", '94' => "objcall", '95' => "supdup", '96' => "dixie", '97' => "swift-rvf", '98' => "tacnews", '99' => "metagram", '101' => "hostname", '102' => "iso-tsap", '103' => "gppitnp", '104' => "acr-nema", '105' => "csnet-ns", '106' => "3com-tsmux", '107' => "rtelnet", '108' => "snagas", '109' => "pop-2", '110' => "pop-3", '111' => "sunrpc", '112' => "mcidas", '113' => "auth", '114' => "audionews", '115' => "sftp", '116' => "ansanotify", '117' => "uucp-path", '118' => "sqlserv", '119' => "nntp", '120' => "cfdptkt", '121' => "erpc", '122' => "smakynet", '123' => "ntp", '124' => "ansatrader", '125' => "locus-map", '126' => "unitary", '127' => "locus-con", '128' => "gss-xlicen", '129' => "pwdgen", '130' => "cisco-fna", '131' => "cisco-tna", '132' => "cisco-sys", '133' => "statsrv", '134' => "ingres-net", '135' => "loc-srv", '136' => "profile", '137' => "netbios-ns", '138' => "netbios-dgm", '139' => "netbios-ssn", '140' => "emfis-data", '141' => "emfis-cntl", '142' => "bl-idm", '143' => "imap2", '144' => "news", '145' => "uaac", '146' => "iso-tp0", '147' => "iso-ip", '148' => "cronus", '149' => "aed-512", '150' => "sql-net", '151' => "hems", '152' => "bftp", '153' => "sgmp", '154' => "netsc-prod", '155' => "netsc-dev", '156' => "sqlsrv", '157' => "knet-cmp", '158' => "pcmail-srv", '159' => "nss-routing", '160' => "sgmp-traps", '161' => "snmp", '162' => "snmptrap", '163' => "cmip-man", '164' => "smip-agent", '165' => "xns-courier", '166' => "s-net", '167' => "namp", '168' => "rsvd", '169' => "send", '170' => "print-srv", '171' => "multiplex", '172' => "cl-1", '173' => "xyplex-mux", '174' => "mailq", '175' => "vmnet", '176' => "genrad-mux", '177' => "xdmcp", '178' => "nextstep", '179' => "bgp", '180' => "ris", '181' => "unify", '182' => "audit", '183' => "ocbinder", '184' => "ocserver", '185' => "remote-kis", '186' => "kis", '187' => "aci", '188' => "mumps", '189' => "qft", '190' => "cacp", '191' => "prospero", '192' => "osu-nms", '193' => "srmp", '194' => "irc", '195' => "dn6-nlm-aud", '196' => "dn6-smm-red", '197' => "dls", '198' => "dls-mon", '199' => "smux", '200' => "src", '201' => "at-rtmp", '202' => "at-nbp", '203' => "at-3", '204' => "at-echo", '205' => "at-5", '206' => "at-zis", '207' => "at-7", '208' => "at-8", '209' => "tam", '210' => "z39.50", '211' => "914c-g", '212' => "anet", '213' => "ipx", '214' => "vmpwscs", '215' => "softpc", '216' => "atls", '217' => "dbase", '218' => "mpp", '219' => "uarps", '220' => "imap3", '221' => "fln-spx", '222' => "rsh-spx", '223' => "cdc", '242' => "direct", '243' => "sur-meas", '244' => "dayna", '245' => "link", '246' => "dsp3270", '247' => "subntbcst_tftp", '248' => "bhfhs", '256' => "rap", '257' => "set", '258' => "yak-chat", '259' => "esro-gen", '260' => "openport", '261' => "nsiiops", '262' => "arcisdms", '263' => "hdap", '264' => "bgmp", '280' => "http-mgmt", '281' => "personal-link", '282' => "cableport-ax", '308' => "novastorbakcup", '309' => "entrusttime", '310' => "bhmds", '311' => "asip-webadmin", '312' => "vslmp", '313' => "magenta-logic", '314' => "opalis-robot", '315' => "dpsi", '316' => "decauth", '317' => "zannet", '321' => "pip", '344' => "pdap", '345' => "pawserv", '346' => "zserv", '347' => "fatserv", '348' => "csi-sgwp", '349' => "mftp", '350' => "matip-type-a", '351' => "matip-type-b", '352' => "dtag-ste-sb", '353' => "ndsauth", '354' => "bh611", '355' => "datex-asn", '356' => "cloanto-net-1", '357' => "bhevent", '358' => "shrinkwrap", '359' => "tenebris_nts", '360' => "scoi2odialog", '361' => "semantix", '362' => "srssend", '363' => "rsvp_tunnel", '364' => "aurora-cmgr", '365' => "dtk", '366' => "odmr", '367' => "mortgageware", '368' => "qbikgdp", '369' => "rpc2portmap", '370' => "codaauth2", '371' => "clearcase", '372' => "ulistserv", '373' => "legent-1", '374' => "legent-2", '375' => "hassle", '376' => "nip", '377' => "tnETOS", '378' => "dsETOS", '379' => "is99c", '380' => "is99s", '381' => "hp-collector", '382' => "hp-managed-node", '383' => "hp-alarm-mgr", '384' => "arns", '385' => "ibm-app", '386' => "asa", '387' => "aurp", '388' => "unidata-ldm", '389' => "ldap", '390' => "uis", '391' => "synotics-relay", '392' => "synotics-broker", '393' => "dis", '394' => "embl-ndt", '395' => "netcp", '396' => "netware-ip", '397' => "mptn", '398' => "kryptolan", '399' => "iso-tsap-c2", '400' => "work-sol", '401' => "ups", '402' => "genie", '403' => "decap", '404' => "nced", '405' => "ncld", '406' => "imsp", '407' => "timbuktu", '408' => "prm-sm", '409' => "prm-nm", '410' => "decladebug", '411' => "rmt", '412' => "synoptics-trap", '413' => "smsp", '414' => "infoseek", '415' => "bnet", '416' => "silverplatter", '417' => "onmux", '418' => "hyper-g", '419' => "ariel1", '420' => "smpte", '421' => "ariel2", '422' => "ariel3", '423' => "opc-job-start", '424' => "opc-job-track", '425' => "icad-el", '426' => "smartsdp", '427' => "svrloc", '428' => "ocs_cmu", '429' => "ocs_amu", '430' => "utmpsd", '431' => "utmpcd", '432' => "iasd", '433' => "nnsp", '434' => "mobileip-agent", '435' => "mobilip-mn", '436' => "dna-cml", '437' => "comscm", '438' => "dsfgw", '439' => "dasp", '440' => "sgcp", '441' => "decvms-sysmgt", '442' => "cvc_hostd", '443' => "https", '444' => "snpp", '445' => "microsoft-ds", '446' => "ddm-rdb", '447' => "ddm-dfm", '448' => "ddm-ssl", '449' => "as-servermap", '450' => "tserver", '451' => "sfs-smp-net", '452' => "sfs-config", '453' => "creativeserver", '454' => "contentserver", '455' => "creativepartnr", '456' => "macon-udp", '457' => "scohelp", '458' => "appleqtc", '459' => "ampr-rcmd", '460' => "skronk", '461' => "datasurfsrv", '462' => "datasurfsrvsec", '463' => "alpes", '464' => "kpasswd5", '465' => "smtps", '466' => "digital-vrc", '467' => "mylex-mapd", '468' => "photuris", '469' => "rcp", '470' => "scx-proxy", '471' => "mondex", '472' => "ljk-login", '473' => "hybrid-pop", '474' => "tn-tl-w2", '475' => "tcpnethaspsrv", '476' => "tn-tl-fd1", '477' => "ss7ns", '478' => "spsc", '479' => "iafserver", '480' => "iafdbase", '481' => "ph", '482' => "xlog", '483' => "ulpnet", '484' => "integra-sme", '485' => "powerburst", '486' => "avian", '487' => "saft", '488' => "gss-http", '489' => "nest-protocol", '490' => "micom-pfs", '491' => "go-login", '492' => "ticf-1", '493' => "ticf-2", '494' => "pov-ray", '495' => "intecourier", '496' => "pim-rp-disc", '497' => "dantz", '498' => "siam", '499' => "iso-ill", '500' => "isakmp", '501' => "stmf", '502' => "asa-appl-proto", '503' => "intrinsa", '504' => "citadel", '505' => "mailbox-lm", '506' => "ohimsrv", '507' => "crs", '508' => "xvttp", '509' => "snare", '510' => "fcp", '511' => "passgo", '512' => "biff", '513' => "who", '514' => "syslog", '515' => "printer", '516' => "videotex", '517' => "talk", '518' => "ntalk", '519' => "utime", '520' => "route", '521' => "ripng", '522' => "ulp", '523' => "ibm-db2", '524' => "ncp", '525' => "timed", '526' => "tempo", '527' => "stx", '528' => "custix", '529' => "irc-serv", '530' => "courier", '531' => "conference", '532' => "netnews", '533' => "netwall", '534' => "mm-admin", '535' => "iiop", '536' => "opalis-rdv", '537' => "nmsp", '538' => "gdomap", '539' => "apertus-ldp", '540' => "uucp", '541' => "uucp-rlogin", '542' => "commerce", '543' => "klogin", '544' => "kshell", '545' => "appleqtcsrvr", '546' => "dhcpv6-client", '547' => "dhcpv6-server", '548' => "afpovertcp", '549' => "idfp", '550' => "new-rwho", '551' => "cybercash", '552' => "deviceshare", '553' => "pirp", '554' => "rtsp", '555' => "dsf", '556' => "remotefs", '557' => "openvms-sysipc", '558' => "sdnskmp", '559' => "teedtap", '560' => "rmonitor", '561' => "monitor", '562' => "chshell", '563' => "snews", '564' => "9pfs", '565' => "whoami", '567' => "banyan-rpc", '568' => "ms-shuttle", '569' => "ms-rome", '570' => "meter", '571' => "umeter", '572' => "sonar", '573' => "banyan-vip", '574' => "ftp-agent", '575' => "vemmi", '576' => "ipcd", '577' => "vnas", '578' => "ipdd", '579' => "decbsrv", '580' => "sntp-heartbeat", '581' => "bdp", '582' => "scc-security", '583' => "philips-vc", '584' => "keyserver", '585' => "imap4-ssl", '586' => "password-chg", '587' => "submission", '588' => "cal", '589' => "eyelink", '590' => "tns-cml", '591' => "http-alt", '592' => "eudora-set", '593' => "http-rpc-epmap", '594' => "tpip", '595' => "cab-protocol", '596' => "smsd", '597' => "ptcnameservice", '598' => "sco-websrvrmg3", '599' => "acp", '600' => "ipcserver", '606' => "urm", '607' => "nqs", '608' => "sift-uft", '609' => "npmp-trap", '610' => "npmp-local", '611' => "npmp-gui", '634' => "ginad", '635' => "mount", '640' => "pcnfs", '650' => "bwnfs", '666' => "doom", '704' => "elcsd", '709' => "entrustmanager", '729' => "netviewdm1", '730' => "netviewdm2", '731' => "netviewdm3", '737' => "sometimes-rpc2", '740' => "netcp", '741' => "netgw", '742' => "netrcs", '744' => "flexlm", '747' => "fujitsu-dev", '748' => "ris-cm", '749' => "kerberos-adm", '750' => "kerberos", '751' => "kerberos_master", '752' => "qrh", '753' => "rrh", '758' => "nlogin", '759' => "con", '760' => "ns", '761' => "rxe", '762' => "quotad", '763' => "cycleserv", '764' => "omserv", '765' => "webster", '767' => "phonebook", '769' => "vid", '770' => "cadlock", '771' => "rtip", '772' => "cycleserv2", '773' => "notify", '774' => "acmaint_dbd", '775' => "acmaint_transd", '776' => "wpages", '780' => "wpgs", '781' => "hp-collector", '782' => "hp-managed-node", '783' => "hp-alarm-mgr", '786' => "concert", '800' => "mdbs_daemon", '801' => "device", '888' => "accessbuilder", '996' => "vsinet", '997' => "maitrd", '998' => "puparp", '999' => "applix", '1000' => "ock", '1008' => "ufsd", '1012' => "sometimes-rpc1", '1025' => "blackjack", '1030' => "iad1", '1031' => "iad2", '1032' => "iad3", '1058' => "nim", '1059' => "nimreg", '1067' => "instl_boots", '1068' => "instl_bootc", '1080' => "socks", '1083' => "ansoft-lm-1", '1084' => "ansoft-lm-2", '1110' => "nfsd-keepalive", '1155' => "nfa", '1167' => "phone", '1212' => "lupa", '1222' => "nerv", '1248' => "hermes", '1346' => "alta-ana-lm", '1347' => "bbn-mmc", '1348' => "bbn-mmx", '1349' => "sbook", '1350' => "editbench", '1351' => "equationbuilder", '1352' => "lotusnotes", '1353' => "relief", '1354' => "rightbrain", '1355' => "intuitive-edge", '1356' => "cuillamartin", '1357' => "pegboard", '1358' => "connlcli", '1359' => "ftsrv", '1360' => "mimer", '1361' => "linx", '1362' => "timeflies", '1363' => "ndm-requester", '1364' => "ndm-server", '1365' => "adapt-sna", '1366' => "netware-csp", '1367' => "dcs", '1368' => "screencast", '1369' => "gv-us", '1370' => "us-gv", '1371' => "fc-cli", '1372' => "fc-ser", '1373' => "chromagrafx", '1374' => "molly", '1375' => "bytex", '1376' => "ibm-pps", '1377' => "cichlid", '1378' => "elan", '1379' => "dbreporter", '1380' => "telesis-licman", '1381' => "apple-licman", '1383' => "gwha", '1384' => "os-licman", '1385' => "atex_elmd", '1386' => "checksum", '1387' => "cadsi-lm", '1388' => "objective-dbc", '1389' => "iclpv-dm", '1390' => "iclpv-sc", '1391' => "iclpv-sas", '1392' => "iclpv-pm", '1393' => "iclpv-nls", '1394' => "iclpv-nlc", '1395' => "iclpv-wsm", '1396' => "dvl-activemail", '1397' => "audio-activmail", '1398' => "video-activmail", '1399' => "cadkey-licman", '1400' => "cadkey-tablet", '1401' => "goldleaf-licman", '1402' => "prm-sm-np", '1403' => "prm-nm-np", '1404' => "igi-lm", '1405' => "ibm-res", '1406' => "netlabs-lm", '1407' => "dbsa-lm", '1408' => "sophia-lm", '1409' => "here-lm", '1410' => "hiq", '1411' => "af", '1412' => "innosys", '1413' => "innosys-acl", '1414' => "ibm-mqseries", '1415' => "dbstar", '1416' => "novell-lu6.2", '1417' => "timbuktu-srv1", '1418' => "timbuktu-srv2", '1419' => "timbuktu-srv3", '1420' => "timbuktu-srv4", '1421' => "gandalf-lm", '1422' => "autodesk-lm", '1423' => "essbase", '1424' => "hybrid", '1425' => "zion-lm", '1426' => "sas-1", '1427' => "mloadd", '1428' => "informatik-lm", '1429' => "nms", '1430' => "tpdu", '1431' => "rgtp", '1432' => "blueberry-lm", '1433' => "ms-sql-s", '1434' => "ms-sql-m", '1435' => "ibm-cics", '1436' => "sas-2", '1437' => "tabula", '1438' => "eicon-server", '1439' => "eicon-x25", '1440' => "eicon-slp", '1441' => "cadis-1", '1442' => "cadis-2", '1443' => "ies-lm", '1444' => "marcam-lm", '1445' => "proxima-lm", '1446' => "ora-lm", '1447' => "apri-lm", '1448' => "oc-lm", '1449' => "peport", '1450' => "dwf", '1451' => "infoman", '1452' => "gtegsc-lm", '1453' => "genie-lm", '1454' => "interhdl_elmd", '1455' => "esl-lm", '1456' => "dca", '1457' => "valisys-lm", '1458' => "nrcabq-lm", '1459' => "proshare1", '1460' => "proshare2", '1461' => "ibm_wrless_lan", '1462' => "world-lm", '1463' => "nucleus", '1464' => "msl_lmd", '1465' => "pipes", '1466' => "oceansoft-lm", '1467' => "csdmbase", '1468' => "csdm", '1469' => "aal-lm", '1470' => "uaiact", '1471' => "csdmbase", '1472' => "csdm", '1473' => "openmath", '1474' => "telefinder", '1475' => "taligent-lm", '1476' => "clvm-cfg", '1477' => "ms-sna-server", '1478' => "ms-sna-base", '1479' => "dberegister", '1480' => "pacerforum", '1481' => "airs", '1482' => "miteksys-lm", '1483' => "afs", '1484' => "confluent", '1485' => "lansource", '1486' => "nms_topo_serv", '1487' => "localinfosrvr", '1488' => "docstor", '1489' => "dmdocbroker", '1490' => "insitu-conf", '1491' => "anynetgateway", '1492' => "stone-design-1", '1493' => "netmap_lm", '1494' => "citrix-ica", '1495' => "cvc", '1496' => "liberty-lm", '1497' => "rfx-lm", '1498' => "watcom-sql", '1499' => "fhc", '1500' => "vlsi-lm", '1501' => "sas-3", '1502' => "shivadiscovery", '1503' => "imtc-mcs", '1504' => "evb-elm", '1505' => "funkproxy", '1506' => "utcd", '1507' => "symplex", '1508' => "diagmond", '1509' => "robcad-lm", '1510' => "mvx-lm", '1511' => "3l-l1", '1512' => "wins", '1513' => "fujitsu-dtc", '1514' => "fujitsu-dtcns", '1515' => "ifor-protocol", '1516' => "vpad", '1517' => "vpac", '1518' => "vpvd", '1519' => "vpvc", '1520' => "atm-zip-office", '1522' => "rna-lm", '1523' => "cichild-lm", '1524' => "ingreslock", '1525' => "orasrv", '1526' => "pdap-np", '1527' => "tlisrv", '1528' => "mciautoreg", '1529' => "coauthor", '1530' => "rap-service", '1531' => "rap-listen", '1532' => "miroconnect", '1533' => "virtual-places", '1534' => "micromuse-lm", '1535' => "ampr-info", '1536' => "ampr-inter", '1537' => "sdsc-lm", '1538' => "3ds-lm", '1539' => "intellistor-lm", '1540' => "rds", '1541' => "rds2", '1542' => "gridgen-elmd", '1543' => "simba-cs", '1544' => "aspeclmd", '1545' => "vistium-share", '1546' => "abbaccuray", '1547' => "laplink", '1548' => "axon-lm", '1549' => "shivasound", '1550' => "3m-image-lm", '1551' => "hecmtl-db", '1552' => "pciarray", '1600' => "issd", '1645' => "radius", '1646' => "radacct", '1650' => "nkd", '1651' => "shiva_confsrvr", '1652' => "xnmp", '1661' => "netview-aix-1", '1662' => "netview-aix-2", '1663' => "netview-aix-3", '1664' => "netview-aix-4", '1665' => "netview-aix-5", '1666' => "netview-aix-6", '1667' => "netview-aix-7", '1668' => "netview-aix-8", '1669' => "netview-aix-9", '1670' => "netview-aix-10", '1671' => "netview-aix-11", '1672' => "netview-aix-12", '1812' => "radius", '1813' => "radacct", '1986' => "licensedaemon", '1987' => "tr-rsrb-p1", '1988' => "tr-rsrb-p2", '1989' => "tr-rsrb-p3", '1990' => "stun-p1", '1991' => "stun-p2", '1992' => "stun-p3", '1993' => "snmp-tcp-port", '1994' => "stun-port", '1995' => "perf-port", '1996' => "tr-rsrb-port", '1997' => "gdp-port", '1998' => "x25-svc-port", '1999' => "tcp-id-port", '2000' => "callbook", '2001' => "wizard", '2002' => "globe", '2004' => "emce", '2005' => "oracle", '2006' => "raid-cc", '2007' => "raid-am", '2008' => "terminaldb", '2009' => "whosockami", '2010' => "pipe_server", '2011' => "servserv", '2012' => "raid-ac", '2013' => "raid-cd", '2014' => "raid-sf", '2015' => "raid-cs", '2016' => "bootserver", '2017' => "bootclient", '2018' => "rellpack", '2019' => "about", '2020' => "xinupageserver", '2021' => "xinuexpansion1", '2022' => "xinuexpansion2", '2023' => "xinuexpansion3", '2024' => "xinuexpansion4", '2025' => "xribs", '2026' => "scrabble", '2027' => "shadowserver", '2028' => "submitserver", '2030' => "device2", '2032' => "blackboard", '2033' => "glogger", '2034' => "scoremgr", '2035' => "imsldoc", '2038' => "objectmanager", '2040' => "lam", '2041' => "interbase", '2042' => "isis", '2043' => "isis-bcast", '2044' => "rimsl", '2045' => "cdfunc", '2046' => "sdfunc", '2047' => "dls", '2048' => "dls-monitor", '2049' => "nfs", '2065' => "dlsrpn", '2067' => "dlswpn", '2103' => "zephyr-clt", '2104' => "zephyr-hm", '2105' => "eklogin", '2106' => "ekshell", '2108' => "rkinit", '2201' => "ats", '2232' => "ivs-video", '2241' => "ivsd", '2307' => "pehelp", '2401' => "cvspserver", '2430' => "venus", '2431' => "venus-se", '2432' => "codasrv", '2433' => "codasrv-se", '2500' => "rtsserv", '2501' => "rtsclient", '2627' => "webster", '2784' => "www-dev", '3049' => "cfs", '3130' => "squid-ipc", '3141' => "vmodem", '3264' => "ccmail", '3333' => "dec-notes", '3421' => "bmap", '3455' => "prsvp", '3456' => "vat", '3457' => "vat-control", '3900' => "udt_os", '3984' => "mapper-nodemgr", '3985' => "mapper-mapethd", '3986' => "mapper-ws_ethd", '4008' => "netcheque", '4045' => "lockd", '4132' => "nuts_dem", '4133' => "nuts_bootp", '4321' => "rwhois", '4343' => "unicall", '4444' => "krb524", '4500' => "sae-urn", '4672' => "rfa", '5000' => "commplex-main", '5001' => "commplex-link", '5002' => "rfe", '5010' => "telelpathstart", '5011' => "telelpathattack", '5050' => "mmcc", '5145' => "rmonitor_secure", '5190' => "aol", '5191' => "aol-1", '5192' => "aol-2", '5193' => "aol-3", '5236' => "padl2sim", '5300' => "hacl-hb", '5301' => "hacl-gs", '5302' => "hacl-cfg", '5303' => "hacl-probe", '5304' => "hacl-local", '5305' => "hacl-test", '5308' => "cfengine", '5500' => "securid", '5540' => "sdxauthd", '5555' => "rplay", '5632' => "pcanywherestat", '5713' => "proshareaudio", '5714' => "prosharevideo", '5715' => "prosharedata", '5716' => "prosharerequest", '5717' => "prosharenotify", '6110' => "softcm", '6111' => "spc", '6141' => "meta-corp", '6142' => "aspentec-lm", '6143' => "watershed-lm", '6144' => "statsci1-lm", '6145' => "statsci2-lm", '6146' => "lonewolf-lm", '6147' => "montage-lm", '6148' => "ricardo-lm", '6502' => "netop-rc", '6558' => "xdsxdm", '6969' => "acmsoda", '7000' => "afs3-fileserver", '7001' => "afs3-callback", '7002' => "afs3-prserver", '7003' => "afs3-vlserver", '7004' => "afs3-kaserver", '7005' => "afs3-volser", '7006' => "afs3-errors", '7007' => "afs3-bos", '7008' => "afs3-update", '7009' => "afs3-rmtsys", '7010' => "ups-onlinet", '7100' => "font-service", '7200' => "fodms", '7201' => "dlip", '7648' => "cucme-1", '7649' => "cucme-2", '7650' => "cucme-3", '7651' => "cucme-4", '9535' => "man", '9876' => "sd", '10080' => "amanda", '17007' => "isode-dua", '18000' => "biimenu", '22370' => "hpnpd", '27444' => "Trinoo_Bcast", '27960' => "Quake3Server", '31335' => "Trinoo_Register", '31337' => "BackOrifice", '32770' => "sometimes-rpc4", '32771' => "sometimes-rpc6", '32772' => "sometimes-rpc8", '32773' => "sometimes-rpc10", '32774' => "sometimes-rpc12", '32775' => "sometimes-rpc14", '32776' => "sometimes-rpc16", '32777' => "sometimes-rpc18", '32778' => "sometimes-rpc20", '32779' => "sometimes-rpc22", '32780' => "sometimes-rpc24", '32786' => "sometimes-rpc26", '32787' => "sometimes-rpc28", '39213' => "sygatefw", '45000' => "ciscopop", '47557' => "dbbrowse", '54321' => "bo2k", ); sub num2udp_serv { return undef unless defined $_[0]; my $name = $num2udp_serv{$_[0]}; defined $name ? $name : $_[0]; } # see # http://www.faqs.org/rfcs/rfc792.html # for icmp types my %num2icmp_type = ( '0' => "echo-reply", '3' => "dest-unreach", '4' => "src-quench", '5' => "redirect", '6' => "alt-host-addr", '8' => "echo", '9' => "router-adv", '10' => "router-sol", '11' => "time-exc", '12' => "para-prob", '13' => "timestamp", '14' => "tstamp-reply", '15' => "info-request", '16' => "info-reply", '17' => "addr-mask-req", '18' => "addr-mask-rep", '30' => "traceroute", '31' => "dgram-conv-err", '32' => "mob-host-red", '33' => "ipv6-where", '34' => "ipv6-here", '35' => "mob-reg-req", '36' => "mob-reg-rep", '37' => "dom-name-req", '38' => "dom-name-rep", '39' => "skip", '40' => "photuris", ); sub num2icmp_type { return undef unless defined $_[0]; my $name = $num2icmp_type{$_[0]}; defined $name ? $name : $_[0]; } # return a true value to keep perl happy 1; __END__ =pod =head1 NAME Lire::Firewall - supplies a subroutine enabling TCP and UDP portnumber-to-name mapping =head1 SYNOPSIS use Lire::Firewall qw/:firewall_number2names /; =head1 DESCRIPTION The Lire::Firewall::firewall_number2names converts numbers for network services, as commonly found in firewall log files, to their descriptive names. firewall_revolve FIXME TODO It takes a firewall Lire dlf object as argument, and operates on its I<to_port>, I<from_port> and I<protocol> properties. TCP services, UDP services and ICMP types are supported. =head1 SEE ALSO RPC 792 for ICMP types. =head1 VERSION $Id: Firewall.pm,v 1.5 2006/07/23 13:16:27 vanbaal Exp $ =head1 COPYRIGHT Copyright (C) 2000, 2001, 2002 Stichting LogReport Foundation LogReport@LogReport.org This file is part of Lire. Lire is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see COPYING); if not, check with http://www.gnu.org/copyleft/gpl.html. =head1 AUTHOR Francis J. Lacoste <flacoste@logreport.org>. The first Lire implementation of a TCP and UDP portnumber-to-name mapping was written by Plamen Bozukov. =cut ����������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/���������������������������������������������������������������������������0000755�0001750�0001750�00000000000�11677607770�012151� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/po/������������������������������������������������������������������������0000755�0001750�0001750�00000000000�11677607770�012567� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/po/fr.mo�������������������������������������������������������������������0000644�0001750�0001750�00000006527�11677606224�013456� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000����������������������������������������������������������������������������������������������������������������������������������������������������������������������������'������T��5���������`�����a�����i�� ���z�� ����� ��������������� ����� �����)�����%��������9�����B�����K�� ���P��;���[�� ����� �����!�����+�����,���'�����T�� ���Y�� ���d��"����������3���������������+���'�� ���S��%���t�������$���������������$�����#���(��x��L������������ ����� ������������� �� ��� �� ���9 �����D ��L���T ��?��� ����� ����� ����� �� ��� ��9��� ��%���; ��.���a ��'��� ��;��� ��3��� �����( �����/ ��"���5 ��'���X ����� ��4��� ����� ����� ��"��� ����� ��)���: �����d ��5��� ��,��� �� ��� ��4��� ��1���% ��������������� ������������� ������$���'�������������������������������"����������������������� ������ ���������#������%��������������������������&����������������������!��� ������ �������% Total�Bytes Downloaded�Client Host�Complete?�Connection ID�Connection identifier. �Contains the file's directory.�Directory�Downloads�Downloads by Directory, Top $dirs_to_show�Downloads by File, Top $files_to_show�Duration�End Time�File�JPEG Files�Name of the authenticated user that did the file transfer. �Select File Filter Specification�Simple Extended Schema for Tests�Simple Schema Definition for Test�Simple extended schema for testing purpose.�Simple schema definition for testing purpose�Size�Start Time�Start time of the file transfer.�Test global filter specification. �Test parameter.�Test report specification using an extended schema.�Test report specification.�The file that was transferred. �The host to which the file was transferred.�The number of bytes transferred.�The time at which the transfer ended.�Time taken by the transfer.�Top Directories Report Specification�Top Files Report Specification�Username�Was the file transferred completely?�selected files matching $file_match�Project-Id-Version: lire 1.4.1 Report-Msgid-Bugs-To: bugs@logreport.org POT-Creation-Date: 2011-12-31 14:22+0100 PO-Revision-Date: 2004-01-23 18:21-0500 Last-Translator: Francis J. Lacoste <flacoste@logreport.org> Language-Team: LogReport Team <logreport@logreport.org> Language: MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit �% total�Octets transfrs�Hte client�Complt ?�ID de connexion�Id de connexion. �Rpertoire du fichier transfr.�Rpertoire�Tlchargements�Tlchargements par rpertoire, les $dirs_to_show avec le plus de transferts�Transferts par fichiers, les $files_to_show les plus transfrs�Dure�Fin�Fichier�Fichiers JPEG�Nom de l'usager authentifi qui a effectu le transfert. �Spcification de filtre : par fichier�Dfinition simple d'un schma tendu pour test�Dfinition simple d'un schma pour test�Dfinition simple d'un schma tendu pour des fins de test.�Dfinition simple d'un schma pour des fins de test�Taille�Dbut�Moment o le transfert a commenc.�Test pour une spcification de filtre. �Paramtre de test�Spcification de rapport utilisant un schma tendu.�Spcification de rapport.�Le fichier transfr. �L'hte qui a transfr le fichier.�Le nombre d'octets transfrs.�Moment auquel le transfert s'est termin.�Temps pris par le transfert�Spcification : rpertoires avec le plus de transfert�Spcification : Fichiers les plus transfrs�Nom d'usager�Est-ce que le fichier a t compltement transfr ?�fichiers slectionns selon le patron $file_match��������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/po/fr.po�������������������������������������������������������������������0000644�0001750�0001750�00000012710�11677606224�013450� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Stichting LogReport Foundation # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: lire 1.4.1\n" "Report-Msgid-Bugs-To: bugs@logreport.org\n" "POT-Creation-Date: 2011-12-31 14:22+0100\n" "PO-Revision-Date: 2004-01-23 18:21-0500\n" "Last-Translator: Francis J. Lacoste <flacoste@logreport.org>\n" "Language-Team: LogReport Team <logreport@logreport.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" #. REFERENCE: report:test:top-files #. REFERENCE: report:test:top-dirs #: lire-test.pot.pl:60 lire-test.pot.pl:70 msgid "% Total" msgstr "% total" #. REFERENCE: report:test:top-dirs #: lire-test.pot.pl:68 msgid "Bytes Downloaded" msgstr "Octets transfrs" #. REFERENCE: schema:test #: lire-test.pot.pl:24 msgid "Client Host" msgstr "Hte client" #. REFERENCE: schema:test #: lire-test.pot.pl:40 msgid "Complete?" msgstr "Complt ?" #. REFERENCE: schema:test #: lire-test.pot.pl:20 msgid "Connection ID" msgstr "ID de connexion" #. REFERENCE: schema:test #: lire-test.pot.pl:22 msgid "Connection identifier. " msgstr "Id de connexion. " #. REFERENCE: schema:test-extended #: lire-test.pot.pl:50 msgid "Contains the file's directory." msgstr "Rpertoire du fichier transfr." #. REFERENCE: schema:test-extended #: lire-test.pot.pl:48 msgid "Directory" msgstr "Rpertoire" #. REFERENCE: report:test:top-files #: lire-test.pot.pl:58 msgid "Downloads" msgstr "Tlchargements" #. REFERENCE: report:test:top-dirs #: lire-test.pot.pl:66 msgid "Downloads by Directory, Top $dirs_to_show" msgstr "" "Tlchargements par rpertoire, les $dirs_to_show avec le plus de transferts" #. REFERENCE: report:test:top-files #: lire-test.pot.pl:56 msgid "Downloads by File, Top $files_to_show" msgstr "Transferts par fichiers, les $files_to_show les plus transfrs" #. REFERENCE: schema:test #: lire-test.pot.pl:16 msgid "Duration" msgstr "Dure" #. REFERENCE: schema:test #: lire-test.pot.pl:12 msgid "End Time" msgstr "Fin" #. REFERENCE: schema:test #: lire-test.pot.pl:32 msgid "File" msgstr "Fichier" #. REFERENCE: test-l10n_cfg.xml #: lire-test.pot.pl:2 msgid "JPEG Files" msgstr "Fichiers JPEG" #. REFERENCE: schema:test #: lire-test.pot.pl:30 msgid "Name of the authenticated user that did the file transfer. " msgstr "Nom de l'usager authentifi qui a effectu le transfert. " #. REFERENCE: filter:test:select-file #: lire-test.pot.pl:72 msgid "Select File Filter Specification" msgstr "Spcification de filtre : par fichier" #. REFERENCE: schema:test-extended #: lire-test.pot.pl:44 msgid "Simple Extended Schema for Tests" msgstr "Dfinition simple d'un schma tendu pour test" #. REFERENCE: schema:test #: lire-test.pot.pl:4 msgid "Simple Schema Definition for Test" msgstr "Dfinition simple d'un schma pour test" #. REFERENCE: schema:test-extended #: lire-test.pot.pl:46 msgid "Simple extended schema for testing purpose." msgstr "Dfinition simple d'un schma tendu pour des fins de test." #. REFERENCE: schema:test #: lire-test.pot.pl:6 msgid "Simple schema definition for testing purpose" msgstr "Dfinition simple d'un schma pour des fins de test" #. REFERENCE: schema:test #: lire-test.pot.pl:36 msgid "Size" msgstr "Taille" #. REFERENCE: schema:test #: lire-test.pot.pl:8 msgid "Start Time" msgstr "Dbut" #. REFERENCE: schema:test #: lire-test.pot.pl:10 msgid "Start time of the file transfer." msgstr "Moment o le transfert a commenc." #. REFERENCE: filter:test:select-file #: lire-test.pot.pl:74 msgid "Test global filter specification. " msgstr "Test pour une spcification de filtre. " #. REFERENCE: filter:test:select-file #: lire-test.pot.pl:76 msgid "Test parameter." msgstr "Paramtre de test" #. REFERENCE: report:test:top-dirs #: lire-test.pot.pl:64 msgid "Test report specification using an extended schema." msgstr "Spcification de rapport utilisant un schma tendu." #. REFERENCE: report:test:top-files #: lire-test.pot.pl:54 msgid "Test report specification." msgstr "Spcification de rapport." #. REFERENCE: schema:test #: lire-test.pot.pl:34 msgid "The file that was transferred. " msgstr "Le fichier transfr. " #. REFERENCE: schema:test #: lire-test.pot.pl:26 msgid "The host to which the file was transferred." msgstr "L'hte qui a transfr le fichier." #. REFERENCE: schema:test #: lire-test.pot.pl:38 msgid "The number of bytes transferred." msgstr "Le nombre d'octets transfrs." #. REFERENCE: schema:test #: lire-test.pot.pl:14 msgid "The time at which the transfer ended." msgstr "Moment auquel le transfert s'est termin." #. REFERENCE: schema:test #: lire-test.pot.pl:18 msgid "Time taken by the transfer." msgstr "Temps pris par le transfert" #. REFERENCE: report:test:top-dirs #: lire-test.pot.pl:62 msgid "Top Directories Report Specification" msgstr "Spcification : rpertoires avec le plus de transfert" #. REFERENCE: report:test:top-files #: lire-test.pot.pl:52 msgid "Top Files Report Specification" msgstr "Spcification : Fichiers les plus transfrs" #. REFERENCE: schema:test #: lire-test.pot.pl:28 msgid "Username" msgstr "Nom d'usager" #. REFERENCE: schema:test #: lire-test.pot.pl:42 msgid "Was the file transferred completely?" msgstr "Est-ce que le fichier a t compltement transfr ?" #. REFERENCE: filter:test:select-file #: lire-test.pot.pl:78 msgid "selected files matching $file_match" msgstr "fichiers slectionns selon le patron $file_match" ��������������������������������������������������������lire-2.1.1/all/lib/tests/po/lire-test.pot.pl��������������������������������������������������������0000644�0001750�0001750�00000005001�11677606224�015542� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# REFERENCE: test-l10n_cfg.xml __( q{JPEG Files} ); # REFERENCE: schema:test __( q{Simple Schema Definition for Test} ); # REFERENCE: schema:test __( q{Simple schema definition for testing purpose} ); # REFERENCE: schema:test __( q{Start Time} ); # REFERENCE: schema:test __( q{Start time of the file transfer.} ); # REFERENCE: schema:test __( q{End Time} ); # REFERENCE: schema:test __( q{The time at which the transfer ended.} ); # REFERENCE: schema:test __( q{Duration} ); # REFERENCE: schema:test __( q{Time taken by the transfer.} ); # REFERENCE: schema:test __( q{Connection ID} ); # REFERENCE: schema:test __( q{Connection identifier. } ); # REFERENCE: schema:test __( q{Client Host} ); # REFERENCE: schema:test __( q{The host to which the file was transferred.} ); # REFERENCE: schema:test __( q{Username} ); # REFERENCE: schema:test __( q{Name of the authenticated user that did the file transfer. } ); # REFERENCE: schema:test __( q{File} ); # REFERENCE: schema:test __( q{The file that was transferred. } ); # REFERENCE: schema:test __( q{Size} ); # REFERENCE: schema:test __( q{The number of bytes transferred.} ); # REFERENCE: schema:test __( q{Complete?} ); # REFERENCE: schema:test __( q{Was the file transferred completely?} ); # REFERENCE: schema:test-extended __( q{Simple Extended Schema for Tests} ); # REFERENCE: schema:test-extended __( q{Simple extended schema for testing purpose.} ); # REFERENCE: schema:test-extended __( q{Directory} ); # REFERENCE: schema:test-extended __( q{Contains the file's directory.} ); # REFERENCE: report:test:top-files __( q{Top Files Report Specification} ); # REFERENCE: report:test:top-files __( q{Test report specification.} ); # REFERENCE: report:test:top-files __( q{Downloads by File, Top $files_to_show} ); # REFERENCE: report:test:top-files __( q{Downloads} ); # REFERENCE: report:test:top-files __( q{% Total} ); # REFERENCE: report:test:top-dirs __( q{Top Directories Report Specification} ); # REFERENCE: report:test:top-dirs __( q{Test report specification using an extended schema.} ); # REFERENCE: report:test:top-dirs __( q{Downloads by Directory, Top $dirs_to_show} ); # REFERENCE: report:test:top-dirs __( q{Bytes Downloaded} ); # REFERENCE: report:test:top-dirs __( q{% Total} ); # REFERENCE: filter:test:select-file __( q{Select File Filter Specification} ); # REFERENCE: filter:test:select-file __( q{Test global filter specification. } ); # REFERENCE: filter:test:select-file __( q{Test parameter.} ); # REFERENCE: filter:test:select-file __( q{selected files matching $file_match} ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/po/Makefile.am�������������������������������������������������������������0000644�0001750�0001750�00000004221�10115407150�014512� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile for various po files. SUPERSERVICE = test COPYRIGHT_HOLDER = Stichting LogReport Foundation MSGID_BUGS_ADDRESS = bugs@logreport.org LINGUAS = fr # you should not modify anything below this line SCHEMAS = $(srcdir)/../schemas/test.xml $(srcdir)/../schemas/test-extended.xml CFGS = $(srcdir)/../data/test-l10n_cfg.xml REPORTS = $(srcdir)/../reports/test/top-files.xml $(srcdir)/../reports/test/top-dirs.xml FILTERS = $(srcdir)/../filters/test/select-file.xml SPECS = $(addprefix report_cfg:, $(CFGS)) \ $(addprefix schema:, $(basename $(notdir $(SCHEMAS)))) \ $(addprefix report:$(SUPERSERVICE):, $(basename $(notdir $(REPORTS)))) \ $(addprefix filter:$(SUPERSERVICE):, $(basename $(notdir $(FILTERS)))) SUFFIXES = .po .mo .pot TEXTDOMAIN = lire-$(SUPERSERVICE) XML_POT_SRC = $(TEXTDOMAIN).pot.pl TEMPLATES = $(TEXTDOMAIN).pot CATALOGS = $(addsuffix .po, $(LINGUAS)) MO_FILES = $(addsuffix .mo, $(LINGUAS)) # MSGMERGE, MSGFMT and XGETTEXT will be set by automake CATOBJEXT = .po TMPLOBJEXT = .pot POTFILES = SUFFIXES = .po .mo .pot BUILT_SOURCES = $(TEMPLATES) $(MO_FILES) $(XML_POT_SRC) MAINTAINERCLEANFILES = $(BUILT_SOURCES) $(XML_POT_SRC): $(SCHEMAS) $(FILTERS) $(REPORTS) $(CFGS) $(PERL) -w -I$(top_srcdir)/all/lib \ $(top_builddir)/all/script/lr_spec2pot \ --cfgspecdir $(top_srcdir)/all/lib/config-spec \ --schemasdir $(srcdir)/../schemas \ --reportsdir $(srcdir)/../reports \ --filtersdir $(srcdir)/../filters \ $(SPECS) > $(XML_POT_SRC) || ( rm -f $(XML_POT_SRC); false) $(TEMPLATES): $(XML_POT_SRC) @echo Updating \'$@\' catalog template. $(XGETTEXT) --sort-output --foreign-user \ --add-comments=REFERENCE: \ --copyright-holder="$(COPYRIGHT_HOLDER)" \ --msgid-bugs-address="$(MSGID_BUGS_ADDRESS)" \ --keyword='$$__' --keyword=__ --keyword=__x \ --keyword=__n:1,2 --keyword=__nx:1,2 --keyword=__xn:1,2 \ --keyword=N__ --language=Perl --output $@ $^ $(CATALOGS): $(TEMPLATES) @if test -f $@; then : ; else cp $< $@; fi $(MSGMERGE) -U $@ $< && touch $@ .po.mo: @echo Generating \'$@\'. $(MSGFMT) --check --statistics --verbose -o $@ $< EXTRA_DIST = $(MO_FILES) $(CATALOGS) $(TEMPLATES) $(XML_POT_SRC) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/po/Makefile.in�������������������������������������������������������������0000644�0001750�0001750�00000026265�11677606133�014557� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile for various po files. VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = all/lib/tests/po DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CYGPATH_W = @CYGPATH_W@ DBKDSSSLPRINT = @DBKDSSSLPRINT@ DBKXSLHTML = @DBKXSLHTML@ DBKXSLHTMLNOCHUNK = @DBKXSLHTMLNOCHUNK@ DBK_XML_DTD = @DBK_XML_DTD@ DEFS = @DEFS@ DIA = @DIA@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ GHOSTSCRIPT = @GHOSTSCRIPT@ GZIP = @GZIP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JADE = @JADE@ LAMBDA = @LAMBDA@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOGGER = @LOGGER@ LR_ARCHIVEDIR = @LR_ARCHIVEDIR@ LR_PERL5LIBDIR = @LR_PERL5LIBDIR@ LR_SPOOLDIR = @LR_SPOOLDIR@ LTLIBOBJS = @LTLIBOBJS@ LYNX = @LYNX@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ ODVIPS = @ODVIPS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFJADETEX = @PDFJADETEX@ PERL = @PERL@ PLOTICUS = @PLOTICUS@ POD2MAN = @POD2MAN@ PS2PDF = @PS2PDF@ SENDMAIL = @SENDMAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TAI64NLOCAL = @TAI64NLOCAL@ TAR = @TAR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ am__leading_dot = @am__leading_dot@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUPERSERVICE = test COPYRIGHT_HOLDER = Stichting LogReport Foundation MSGID_BUGS_ADDRESS = bugs@logreport.org LINGUAS = fr # you should not modify anything below this line SCHEMAS = $(srcdir)/../schemas/test.xml $(srcdir)/../schemas/test-extended.xml CFGS = $(srcdir)/../data/test-l10n_cfg.xml REPORTS = $(srcdir)/../reports/test/top-files.xml $(srcdir)/../reports/test/top-dirs.xml FILTERS = $(srcdir)/../filters/test/select-file.xml SPECS = $(addprefix report_cfg:, $(CFGS)) \ $(addprefix schema:, $(basename $(notdir $(SCHEMAS)))) \ $(addprefix report:$(SUPERSERVICE):, $(basename $(notdir $(REPORTS)))) \ $(addprefix filter:$(SUPERSERVICE):, $(basename $(notdir $(FILTERS)))) SUFFIXES = .po .mo .pot TEXTDOMAIN = lire-$(SUPERSERVICE) XML_POT_SRC = $(TEXTDOMAIN).pot.pl TEMPLATES = $(TEXTDOMAIN).pot CATALOGS = $(addsuffix .po, $(LINGUAS)) MO_FILES = $(addsuffix .mo, $(LINGUAS)) # MSGMERGE, MSGFMT and XGETTEXT will be set by automake CATOBJEXT = .po TMPLOBJEXT = .pot POTFILES = BUILT_SOURCES = $(TEMPLATES) $(MO_FILES) $(XML_POT_SRC) MAINTAINERCLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = $(MO_FILES) $(CATALOGS) $(TEMPLATES) $(XML_POT_SRC) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .po .mo .pot $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu all/lib/tests/po/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu all/lib/tests/po/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: all check install install-am install-strip .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am $(XML_POT_SRC): $(SCHEMAS) $(FILTERS) $(REPORTS) $(CFGS) $(PERL) -w -I$(top_srcdir)/all/lib \ $(top_builddir)/all/script/lr_spec2pot \ --cfgspecdir $(top_srcdir)/all/lib/config-spec \ --schemasdir $(srcdir)/../schemas \ --reportsdir $(srcdir)/../reports \ --filtersdir $(srcdir)/../filters \ $(SPECS) > $(XML_POT_SRC) || ( rm -f $(XML_POT_SRC); false) $(TEMPLATES): $(XML_POT_SRC) @echo Updating \'$@\' catalog template. $(XGETTEXT) --sort-output --foreign-user \ --add-comments=REFERENCE: \ --copyright-holder="$(COPYRIGHT_HOLDER)" \ --msgid-bugs-address="$(MSGID_BUGS_ADDRESS)" \ --keyword='$$__' --keyword=__ --keyword=__x \ --keyword=__n:1,2 --keyword=__nx:1,2 --keyword=__xn:1,2 \ --keyword=N__ --language=Perl --output $@ $^ $(CATALOGS): $(TEMPLATES) @if test -f $@; then : ; else cp $< $@; fi $(MSGMERGE) -U $@ $< && touch $@ .po.mo: @echo Generating \'$@\'. $(MSGFMT) --check --statistics --verbose -o $@ $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/po/lire-test.pot�����������������������������������������������������������0000644�0001750�0001750�00000010476�11677606224�015144� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Stichting LogReport Foundation # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: bugs@logreport.org\n" "POT-Creation-Date: 2011-12-31 14:22+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #. REFERENCE: report:test:top-files #. REFERENCE: report:test:top-dirs #: lire-test.pot.pl:60 lire-test.pot.pl:70 msgid "% Total" msgstr "" #. REFERENCE: report:test:top-dirs #: lire-test.pot.pl:68 msgid "Bytes Downloaded" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:24 msgid "Client Host" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:40 msgid "Complete?" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:20 msgid "Connection ID" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:22 msgid "Connection identifier. " msgstr "" #. REFERENCE: schema:test-extended #: lire-test.pot.pl:50 msgid "Contains the file's directory." msgstr "" #. REFERENCE: schema:test-extended #: lire-test.pot.pl:48 msgid "Directory" msgstr "" #. REFERENCE: report:test:top-files #: lire-test.pot.pl:58 msgid "Downloads" msgstr "" #. REFERENCE: report:test:top-dirs #: lire-test.pot.pl:66 msgid "Downloads by Directory, Top $dirs_to_show" msgstr "" #. REFERENCE: report:test:top-files #: lire-test.pot.pl:56 msgid "Downloads by File, Top $files_to_show" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:16 msgid "Duration" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:12 msgid "End Time" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:32 msgid "File" msgstr "" #. REFERENCE: test-l10n_cfg.xml #: lire-test.pot.pl:2 msgid "JPEG Files" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:30 msgid "Name of the authenticated user that did the file transfer. " msgstr "" #. REFERENCE: filter:test:select-file #: lire-test.pot.pl:72 msgid "Select File Filter Specification" msgstr "" #. REFERENCE: schema:test-extended #: lire-test.pot.pl:44 msgid "Simple Extended Schema for Tests" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:4 msgid "Simple Schema Definition for Test" msgstr "" #. REFERENCE: schema:test-extended #: lire-test.pot.pl:46 msgid "Simple extended schema for testing purpose." msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:6 msgid "Simple schema definition for testing purpose" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:36 msgid "Size" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:8 msgid "Start Time" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:10 msgid "Start time of the file transfer." msgstr "" #. REFERENCE: filter:test:select-file #: lire-test.pot.pl:74 msgid "Test global filter specification. " msgstr "" #. REFERENCE: filter:test:select-file #: lire-test.pot.pl:76 msgid "Test parameter." msgstr "" #. REFERENCE: report:test:top-dirs #: lire-test.pot.pl:64 msgid "Test report specification using an extended schema." msgstr "" #. REFERENCE: report:test:top-files #: lire-test.pot.pl:54 msgid "Test report specification." msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:34 msgid "The file that was transferred. " msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:26 msgid "The host to which the file was transferred." msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:38 msgid "The number of bytes transferred." msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:14 msgid "The time at which the transfer ended." msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:18 msgid "Time taken by the transfer." msgstr "" #. REFERENCE: report:test:top-dirs #: lire-test.pot.pl:62 msgid "Top Directories Report Specification" msgstr "" #. REFERENCE: report:test:top-files #: lire-test.pot.pl:52 msgid "Top Files Report Specification" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:28 msgid "Username" msgstr "" #. REFERENCE: schema:test #: lire-test.pot.pl:42 msgid "Was the file transferred completely?" msgstr "" #. REFERENCE: filter:test:select-file #: lire-test.pot.pl:78 msgid "selected files matching $file_match" msgstr "" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/LrRangegroupTest.pm��������������������������������������������������������0000644�0001750�0001750�00000010124�10460672577�015670� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::LrRangegroupTest; use strict; use base qw/Lire::Test::TestCase/; use Lire::SQLExt::LrRangegroup; sub test_lr_rangegroup { my $self = $_[0]; my @tests = ( # Value, Start, Length, Min, Max, Result [ undef, 0, 10, undef, undef, undef ], [ 10, undef, 10, undef, undef, undef ], [ 10, 0, undef, undef, undef, undef ], [ 0, 0, 10, undef, undef, 0 ], [ 5, 0, 10, undef, undef, 0 ], [ 10, 0, 10, undef, undef, 10 ], [ 10_000, 0, 10, undef, 1_000, 1_000 ], [ -1, 0, 10, undef, undef, -10 ], [ -10, 0, 10, undef, undef, -10 ], [ -1, 0, 10, 0, undef, 0 ], [ 2, 1, 10, undef, undef, 1], [ 0, 1, 10, undef, undef, -9], [ 0, 1, 10, 1, undef, 1], ); foreach my $t ( @tests ) { my ( $value, $start, $length, $min, $max, $result ) = @$t; my $r = Lire::SQLExt::LrRangegroup::lr_rangegroup( $value, $start, $length, $min, $max ); no warnings 'uninitialized'; if ( ! defined $result ) { $self->assert_null( $r, "lr_rangegroup( $value, $start, $length, $min, $max ) should return undef, not $r" ); } else { $self->assert_not_null( $r, "lr_rangegroup( $value, $start, $length, $min, $max ) should return $result, not undef" ); $self->assert_equals( $result, $r, "lr_rangegroup( $value, $start, $length, $min, $max ) returned $r, expected $result" ); } } } sub test_lr_rangegroup_geo { my $self = $_[0]; my @tests = ( # Value, Start, Length, Base, Min, Max, Result [ undef, 0, 10, 2, undef, undef, undef ], [ 10, undef, 10, 2, undef, undef, undef ], [ 10, 0, undef, 2, undef, undef, undef ], [ 10, 0, 2, undef, undef, undef, undef ], # [0-1000> # [1000-6000> # [6000-31000> # [31000,~ [ -1, 0, 1000, 5, undef, undef, undef ], [ 0, 0, 1000, 5, undef, undef, 0 ], [ 1000, 0, 1000, 5, undef, undef, 1000 ], [ 6_000, 0, 1000, 5, undef, undef, 6_000 ], [ 23_000, 0, 1000, 5, undef, undef, 6_000 ], [ 30_000, 0, 1000, 5, undef, undef, 6_000 ], [ 31_000, 0, 1000, 5, undef, undef, 31_000 ], [ 200_000, 0, 1000, 5, undef, 50_000, 31_000 ], [ 10, 0, 1000, 5, 1000, undef, 1000 ], # [1-11> # [11-31> # [31-71> # [71-~ [ 0, 1, 10, 2, undef, undef, undef ], [ 1, 1, 10, 2, undef, undef, 1 ], [ 10, 1, 10, 2, undef, undef, 1 ], [ 11, 1, 10, 2, undef, undef, 11 ], [ 30, 1, 10, 2, undef, undef, 11 ], [ 30.9999, 1, 10, 2, undef, undef, 11 ], [ 31, 1, 10, 2, undef, undef, 31 ], [ 40, 1, 10, 2, undef, undef, 31 ], [ 71, 1, 10, 2, undef, undef, 71 ], # [5-15> # [15-35> # [35-75> # [75-~ [ 0, 5, 10, 2, undef, undef, undef ], [ 0, 5, 10, 2, 5, undef, 5 ], [ 5, 5, 10, 2, undef, undef, 5 ], [ 10, 5, 10, 2, undef, undef, 5 ], [ 11, 5, 10, 2, undef, undef, 5 ], [ 30, 5, 10, 2, undef, undef, 15 ], [ 40, 5, 10, 2, undef, undef, 35 ], [ 70, 5, 10, 2, undef, undef, 35 ], [ 75, 5, 10, 2, undef, undef, 75 ], ); foreach my $t ( @tests ) { my ( $value, $start, $length, $base, $min, $max, $result ) = @$t; my $r = Lire::SQLExt::LrRangegroup::lr_rangegroup_geo( $value, $start, $length, $base, $min, $max ); no warnings 'uninitialized'; if ( ! defined $result ) { $self->assert_null( $r, "lr_rangegroup( $value, $start, $length, $base, $min, $max ) should return undef, not $r" ); } else { $self->assert_not_null( $r, "lr_rangegroup( $value, $start, $length, $base, $min, $max ) should return $result, not undef" ); $self->assert_equals( $result, $r, "lr_rangegroup( $value, $start, $length, $base, $min, $max ) returned $r, expected $result" ); } } } 1; ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/ReportParserAsciiWriterTest.pm���������������������������������������������0000644�0001750�0001750�00000004364�10460672601�020054� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::ReportParserAsciiWriterTest; use base qw/Lire::Test::TestCase tests::TestStoreFixture/; use Lire::ReportParser::AsciiWriter; use Lire::Utils qw/tempfile/; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->init(); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); unlink $self->{'unlink'} if $self->{'unlink'}; return; } sub test_new { my $self = $_[0]; my $parser = new Lire::ReportParser::AsciiWriter(); $self->assert_isa( 'Lire::ReportParser::AsciiWriter', $parser ); $self->assert_num_equals( 74, $parser->{'columns'} ); $self->assert_num_equals( 180, $parser->{'max_name_len'} ); $self->assert_str_equals( \*STDOUT, $parser->{'_fh'} ); $self->assert_str_equals( '', $parser->{'_encoding'} ); my $fh = tempfile(); $parser = new Lire::ReportParser::AsciiWriter( 'output' => $fh, 'encoding' => 'UTF-8', 'columns' => 70, 'max_name_length' => 100, ); $self->assert_isa( 'Lire::ReportParser::AsciiWriter', $parser ); $self->assert_num_equals( 70, $parser->{'columns'} ); $self->assert_num_equals( 100, $parser->{'max_name_len'} ); $self->assert_str_equals( $fh, $parser->{'_fh'} ); $self->assert_str_equals( 'UTF-8', $parser->{'_encoding'} ); } sub test_parsefile { my $self = $_[0]; my ( $fh, $file ) = tempfile( 'report_XXXXXX', 'SUFFIX' => '.txt' ); $self->{'unlink'} = $file; my $parser = new Lire::ReportParser::AsciiWriter( 'output' => $fh, 'encoding' => 'UTF-16LE' ); $parser->parsefile( "$self->{'testdir'}/data/test-utf8.xml" ); close $fh; open my $exp_fh, "$self->{'testdir'}/data/test-utf-16le.txt" or die "open failed: $!"; open my $gen_fh, $file or die "open failed: $!"; local $/ = undef; my $expected = <$exp_fh>; my $generated = <$gen_fh>; $expected =~ s/\0/./g; $generated =~ s/\0/./g; $self->assert_str_equals( $expected, $generated ); } 1; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/ChartTypesDistTest.pm������������������������������������������������������0000644�0001750�0001750�00000006020�10460672577�016173� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::ChartTypesDistTest; use strict; use base qw/Lire::Test::PluginTestCase/; use Lire::ChartTypes::Dist; use Lire::Config::Build qw/ac_info/; use Lire::Config::ChartSpec; use Lire::Config::ExecutableSpec; use Lire::PluginManager; use Lire::ReportParser::ReportBuilder; use Lire::Utils qw/tempdir/; use File::Basename qw/dirname/; use IO::Scalar; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'cfg'}{'ploticus_path'} = new Lire::Config::ExecutableSpec( 'name' => 'ploticus_path' )->instance( 'value' => ac_info( 'PLOTICUS' ) ); $self->{'cfg'}{'lr_chart_font'} = ''; $self->{'chart_cfg'} = new Lire::Config::ChartSpec( 'name' => 'chart' )->instance(); return; } sub create_plugin { return new Lire::ChartTypes::Dist(); } sub properties_spec_file { return dirname( __FILE__ ) . "/../Lire/ChartTypes/ct_dist.xml"; } sub registration_file { return dirname( __FILE__ ) . "/../Lire/ChartTypes/ct_dist_init"; } sub set_up_subreport { my $self = $_[0]; my $parser = new Lire::ReportParser::ReportBuilder(); my $report = $parser->parsefile( dirname( __FILE__ ) . "/data/test-sqlite.xml" ); $self->{'subreport'} = $report->subreport_by_id( 'top-files.0' ); } sub test_write_parameters { my $self = $_[0]; $self->set_up_subreport(); $self->test_registration_file(); $self->{'chart_cfg'}->get( 'type' )->set_plugin( 'dist' ); my $dist = Lire::PluginManager->get_plugin( 'chart_type', 'dist' ); my $fh = new IO::Scalar; my $buf = $fh->sref(); $self->{'subreport'}->table_info()->set_variables_indices(); $self->{'chart_cfg'}->type_properties()->get( 'x' )->set( 'request_total' ); $dist->write_parameters( $self->{'chart_cfg'}, $fh ); $self->assert_matches( qr/#set x = 2\n#set curve = yes/, $$buf ); $$buf = ''; $self->{'chart_cfg'}->type_properties()->get( 'curve' )->set( 0 ); $dist->write_parameters( $self->{'chart_cfg'}, $fh ); $self->assert_matches( qr/#set x = 2\n#set curve = no/, $$buf ); } sub test_write_chart { my $self = $_[0]; my $keep = $ENV{'KEEP_CHART'} || 0; my $parser = new Lire::ReportParser::ReportBuilder(); my $report = $parser->parsefile( dirname( __FILE__ ) . "/data/test-sqlite.xml" ); my $subreport = $report->subreport_by_id( 'top-files.0' ); $self->test_registration_file(); $self->{'chart_cfg'}->get( 'name' )->set( 'dist' ); $self->{'chart_cfg'}->get( 'type' )->set_plugin( 'dist' ); my $dist = Lire::PluginManager->get_plugin( 'chart_type', 'dist' ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'file' ); $self->{'chart_cfg'}->get( 'type' )->get_properties()->get( 'x' )->set( 'request_total' ); my $dir = tempdir( $self->name() . '_XXXXXX', CLEANUP => !$keep ); my $chart = $dist->write_chart( $self->{'chart_cfg'}, $subreport, 'outputdir' => $dir, 'format' => 'png', ); $self->assert( -f $chart ? 1 : 0, "file '$chart' not created" ); warn( "\nChart written in: $chart\n" ) if $keep; } 1; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/WeekCalculatorTest.pm������������������������������������������������������0000644�0001750�0001750�00000026362�10460672600�016164� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::WeekCalculatorTest; use strict; use base qw/Lire::Test::TestCase/; use Lire::WeekCalculator; use Time::Local; my @week_no_data = ( [788961600, '01', '52', '00'], [789048000, '01', '01', '01'], [789134400, '01', '01', '01'], [789220800, '01', '01', '01'], [789307200, '01', '01', '01'], [789393600, '01', '01', '01'], [789480000, '01', '01', '01'], [789566400, '02', '01', '01'], [819720000, '51', '51', '51'], [819806400, '52', '51', '51'], [819892800, '52', '52', '52'], [819979200, '52', '52', '52'], [820065600, '52', '52', '52'], [820152000, '52', '52', '52'], [820238400, '52', '52', '52'], [820324800, '52', '52', '52'], [820411200, '53', '52', '52'], [820497600, '00', '01', '01'], [820584000, '00', '01', '01'], [820670400, '00', '01', '01'], [820756800, '00', '01', '01'], [820843200, '00', '01', '01'], [820929600, '00', '01', '01'], [821016000, '01', '01', '01'], [821102400, '01', '02', '02'], [851342400, '51', '52', '52'], [851428800, '51', '52', '52'], [851515200, '51', '52', '52'], [851601600, '51', '52', '52'], [851688000, '51', '52', '52'], [851774400, '51', '52', '52'], [851860800, '52', '52', '52'], [851947200, '52', '01', '53'], [852033600, '52', '01', '53'], [852120000, '00', '01', '00'], [852206400, '00', '01', '00'], [852292800, '00', '01', '00'], [852379200, '00', '01', '00'], [852465600, '01', '01', '00'], [852552000, '01', '02', '01'], [852638400, '01', '02', '01'], [852724800, '01', '02', '01'], [882878400, '51', '52', '51'], [882964800, '51', '52', '51'], [883051200, '51', '52', '51'], [883137600, '51', '52', '51'], [883224000, '51', '52', '51'], [883310400, '52', '52', '51'], [883396800, '52', '01', '52'], [883483200, '52', '01', '52'], [883569600, '52', '01', '52'], [883656000, '00', '01', '00'], [883742400, '00', '01', '00'], [883828800, '00', '01', '00'], [883915200, '01', '01', '00'], [884001600, '01', '02', '01'], [884088000, '01', '02', '01'], [884174400, '01', '02', '01'], [884260800, '01', '02', '01'], [914414400, '51', '52', '51'], [914500800, '51', '52', '51'], [914587200, '51', '52', '51'], [914673600, '51', '52', '51'], [914760000, '52', '52', '51'], [914846400, '52', '53', '52'], [914932800, '52', '53', '52'], [915019200, '52', '53', '52'], [915105600, '52', '53', '52'], [915192000, '00', '53', '00'], [915278400, '00', '53', '00'], [915364800, '01', '53', '00'], [915451200, '01', '01', '01'], [915537600, '01', '01', '01'], [915624000, '01', '01', '01'], [915710400, '01', '01', '01'], [915796800, '01', '01', '01'], [945950400, '51', '51', '51'], [946036800, '51', '51', '51'], [946123200, '51', '51', '51'], [946209600, '52', '51', '51'], [946296000, '52', '52', '52'], [946382400, '52', '52', '52'], [946468800, '52', '52', '52'], [946555200, '52', '52', '52'], [946641600, '52', '52', '52'], [946728000, '00', '52', '00'], [946814400, '01', '52', '00'], [946900800, '01', '01', '01'], [946987200, '01', '01', '01'], [947073600, '01', '01', '01'], [947160000, '01', '01', '01'], [947246400, '01', '01', '01'], [947332800, '01', '01', '01'], [977572800, '51', '51', '51'], [977659200, '52', '51', '51'], [977745600, '52', '52', '52'], [977832000, '52', '52', '52'], [977918400, '52', '52', '52'], [978004800, '52', '52', '52'], [978091200, '52', '52', '52'], [978177600, '52', '52', '52'], [978264000, '53', '52', '52'], [978350400, '00', '01', '01'], [978436800, '00', '01', '01'], [978523200, '00', '01', '01'], [978609600, '00', '01', '01'], [978696000, '00', '01', '01'], [978782400, '00', '01', '01'], [978868800, '01', '01', '01'], [978955200, '01', '02', '02'], [1009108800, '51', '51', '51'], [1009195200, '51', '52', '52'], [1009281600, '51', '52', '52'], [1009368000, '51', '52', '52'], [1009454400, '51', '52', '52'], [1009540800, '51', '52', '52'], [1009627200, '51', '52', '52'], [1009713600, '52', '52', '52'], [1009800000, '52', '01', '53'], [1009886400, '00', '01', '00'], [1009972800, '00', '01', '00'], [1010059200, '00', '01', '00'], [1010145600, '00', '01', '00'], [1010232000, '00', '01', '00'], [1010318400, '01', '01', '00'], [1010404800, '01', '02', '01'], [1010491200, '01', '02', '01'], [1040644800, '51', '52', '51'], [1040731200, '51', '52', '51'], [1040817600, '51', '52', '51'], [1040904000, '51', '52', '51'], [1040990400, '51', '52', '51'], [1041076800, '51', '52', '51'], [1041163200, '52', '52', '51'], [1041249600, '52', '01', '52'], [1041336000, '52', '01', '52'], [1041422400, '00', '01', '00'], [1041508800, '00', '01', '00'], [1041595200, '00', '01', '00'], [1041681600, '00', '01', '00'], [1041768000, '01', '01', '00'], [1041854400, '01', '02', '01'], [1041940800, '01', '02', '01'], [1042027200, '01', '02', '01'], [1072180800, '51', '52', '51'], [1072267200, '51', '52', '51'], [1072353600, '51', '52', '51'], [1072440000, '51', '52', '51'], [1072526400, '51', '52', '51'], [1072612800, '52', '52', '51'], [1072699200, '52', '01', '52'], [1072785600, '52', '01', '52'], [1072872000, '52', '01', '52'], [1072958400, '00', '01', '00'], [1073044800, '00', '01', '00'], [1073131200, '00', '01', '00'], [1073217600, '01', '01', '00'], [1073304000, '01', '02', '01'], [1073390400, '01', '02', '01'], [1073476800, '01', '02', '01'], [1073563200, '01', '02', '01'], [1103803200, '51', '52', '51'], [1103889600, '51', '52', '51'], [1103976000, '51', '52', '51'], [1104062400, '52', '52', '51'], [1104148800, '52', '53', '52'], [1104235200, '52', '53', '52'], [1104321600, '52', '53', '52'], [1104408000, '52', '53', '52'], [1104494400, '52', '53', '52'], [1104580800, '00', '53', '00'], [1104667200, '01', '53', '00'], [1104753600, '01', '01', '01'], [1104840000, '01', '01', '01'], [1104926400, '01', '01', '01'], [1105012800, '01', '01', '01'], [1105099200, '01', '01', '01'], [1105185600, '01', '01', '01'], [1135339200, '51', '51', '51'], [1135425600, '51', '51', '51'], [1135512000, '52', '51', '51'], [1135598400, '52', '52', '52'], [1135684800, '52', '52', '52'], [1135771200, '52', '52', '52'], [1135857600, '52', '52', '52'], [1135944000, '52', '52', '52'], [1136030400, '52', '52', '52'], ); my @last_week_data = ( [1990, 52, 52, 53], [1991, 52, 52, 52], [1992, 52, 53, 52], [1993, 52, 52, 52], [1994, 52, 52, 52], [1995, 53, 52, 52], [1996, 52, 52, 53], [1997, 52, 52, 52], [1998, 52, 53, 52], [1999, 52, 52, 52], [2000, 53, 52, 52], [2001, 52, 52, 53], [2002, 52, 52, 52], [2003, 52, 52, 52], [2004, 52, 53, 52], [2005, 52, 52, 52], [2006, 53, 52, 52], [2007, 52, 52, 53], [2008, 52, 52, 52], [2009, 52, 53, 52], [2010, 52, 52, 52], ); my @first_week_data = ( [1990, 631670400, 631152000, 631152000], [1991, 663120000, 662601600, 663206400], [1992, 694569600, 694051200, 694656000], [1993, 726019200, 726105600, 726105600], [1994, 757468800, 757555200, 757555200], [1995, 788918400, 789004800, 789004800], [1996, 820972800, 820454400, 820454400], [1997, 852422400, 851904000, 852508800], [1998, 883872000, 883353600, 883958400], [1999, 915321600, 915408000, 915408000], [2000, 946771200, 946857600, 946857600], [2001, 978825600, 978307200, 978307200], [2002, 1010275200, 1009756800, 1010361600], [2003, 1041724800, 1041206400, 1041811200], [2004, 1073174400, 1072656000, 1073260800], [2005, 1104624000, 1104710400, 1104710400], [2006, 1136073600, 1136160000, 1136160000], [2007, 1168128000, 1167609600, 1167609600], [2008, 1199577600, 1199059200, 1199664000], [2009, 1231027200, 1230508800, 1231113600], [2010, 1262476800, 1262563200, 1262563200], ); sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'cfg'}{'lr_week_numbering'} = 'ISO'; $self->set_up_tz( 'UTC' ); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub test_new { my $self = $_[0]; for my $style ( [ undef, '%V' ], [ 'U', '%U' ], [ 'W', '%W' ], [ 'ISO', '%V' ] ) { my $calc = new Lire::WeekCalculator( 'style' => $style->[0] ); $self->assert( UNIVERSAL::isa( $calc, 'Lire::WeekCalculator' ), "new() returned wrong instance" ); $self->assert_equals( $style->[1], $calc->{'fmt'} ); } $self->assert_died( sub { new Lire::WeekCalculator( 'style' => 'wrong' )}, qr/invalid week numbering style/ ); $self->assert_not_null( $Lire::WeekCalculator::haveV, "haveV wasn't set" ); } sub run_test_on_method { my ( $self, $method, $data ) = @_; no strict 'refs'; my $u = new Lire::WeekCalculator( 'style' => 'U' ); my $v = new Lire::WeekCalculator( 'style' => 'ISO' ); my $w = new Lire::WeekCalculator( 'style' => 'W' ); foreach ( @$data ) { $self->assert_equals($_->[1], $u->$method($_->[0])); $self->assert_equals($_->[2], $v->$method($_->[0])); $self->assert_equals($_->[3], $w->$method($_->[0])); } } sub test_week_number { my $self = $_[0]; $self->run_test_on_method( 'week_number', \@week_no_data ); } sub test_week_number_own_V { my $self = $_[0]; local $Lire::WeekCalculator::haveV = 0; $self->run_test_on_method( 'week_number', \@week_no_data ); } sub test_last_week_of_year { my $self = $_[0]; $self->run_test_on_method( 'last_week_of_year', \@last_week_data ); } sub test_last_week_of_year_V { my $self = $_[0]; local $Lire::WeekCalculator::haveV = 0; $self->run_test_on_method( 'last_week_of_year', \@last_week_data ); } sub test_find_year_week1_start_date { my $self = $_[0]; $self->run_test_on_method( 'find_year_week1_start_date', \@first_week_data ); } sub test_find_year_week1_start_date_V { my $self = $_[0]; local $Lire::WeekCalculator::haveV = 0; $self->run_test_on_method( 'find_year_week1_start_date', \@first_week_data ); } sub test_week_idx { my $self = $_[0]; my $calc = new Lire::WeekCalculator( 'style' => 'ISO' ); $self->assert_num_equals( 0, $calc->week_idx( timelocal( 0, 0, 0, 1, 0, 2004 ) ) ); $self->assert_num_equals( 0, $calc->week_idx( timelocal( 0, 0, 0, 31, 11, 2003 ) ) ); $self->assert_num_equals( 4, $calc->week_idx( timelocal( 0, 0, 0, 1, 1, 2004 ) ) ); $calc = new Lire::WeekCalculator( 'style' => 'U' ); $self->assert_num_equals( 51, $calc->week_idx( timelocal( 0, 0, 0, 1, 0, 2004 ) ) ); $self->assert_num_equals( 51, $calc->week_idx( timelocal( 0, 0, 0, 31, 11, 2003 ) ) ); $self->assert_num_equals( 4, $calc->week_idx( timelocal( 0, 0, 0, 1, 1, 2004 ) ) ); $calc = new Lire::WeekCalculator( 'style' => 'W' ); $self->assert_num_equals( 51, $calc->week_idx( timelocal( 0, 0, 0, 1, 0, 2004 ) ) ); $self->assert_num_equals( 51, $calc->week_idx( timelocal( 0, 0, 0, 31, 11, 2003 ) ) ); $self->assert_num_equals( 3, $calc->week_idx( timelocal( 0, 0, 0, 1, 1, 2004 ) ) ); } 1; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/DlfQueryTest.pm������������������������������������������������������������0000644�0001750�0001750�00000116252�10460672600�015010� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::DlfQueryTest; use strict; use base qw/ tests::TestStoreFixture Lire::Test::TestCase /; use Lire::DlfQuery; use Lire::DlfSchema; use Lire::ExtendedSchema; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->set_up_test_schema(); $Lire::DlfSchema::SCHEMA_CACHE{'test-extended2'} = new Lire::ExtendedSchema( 'id' => 'test-extended2', 'base-schema' => 'test-derived', 'module' => 'MyModule' ); $self->{'query'} = new Lire::DlfQuery( 'test' ); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); delete $Lire::DlfSchema::SCHEMA_CACHE{'test-extended2'}; $self->tear_down_test_store() if $self->{'store'}; $self->{'query'}->release(); return; } sub test_new { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_isa( 'Lire::DlfQuery', $query ); $self->assert_num_equals( 0, $query->{'_limit'} ); $self->assert_null( $query->{'_sort_spec'}, "'_sort_spec' attribute should be undef" ); $self->assert_null( $query->{'_order_by'}, "'_order_by' attribute should be undef" ); $self->assert_deep_equals( [], $query->{'_fields'} ); $self->assert_deep_equals( {}, $query->{'_field_refs'} ); $self->assert_deep_equals( [], $query->{'_filter_params'}); $self->assert_null( $query->{'_parent'}, "new query should have NULL parent" ); $self->assert_deep_equals( [], $query->{'_nested_queries'} ); $self->assert_null( $query->{'_filter_clause'}, "filter_clause attribute should be undef" ); $self->assert_str_equals( 'test', $query->{'_stream_name'} ); } sub test_new_bad_params { my $self = $_[0]; $self->assert_dies( qr/missing 'stream_name' parameter/, sub { new Lire::DlfQuery() } ); $self->assert_dies( qr/there is no schema 'wawa'/, sub { new Lire::DlfQuery( 'wawa' ) } ); } sub test__schema_has_field { my $self = $_[0]; $self->assert( $self->{'query'}->_schema_has_field( 'time_start' ) ); $self->assert( ! $self->{'query'}->_schema_has_field( 'dirname' ) ); $self->{'query'}{'_joined_streams'} = [ 'test-extended' ]; $self->assert( $self->{'query'}->_schema_has_field( 'dirname' ) ); } sub test__field_by_name { my $self = $_[0]; my $query = $self->{'query'}; $query->_add_field ('file', 'simple'); $self->assert_deep_equals ( { 'field' => 'file', 'type' => 'simple', 'alias' => undef }, $query->_field_by_name('file') ); $query->_add_field ('sum()', 'aggr', 'count'); $self->assert_deep_equals ( { 'field' => 'sum()', 'type' => 'aggr', 'alias' => 'count' }, $query->_field_by_name('count') ); } sub test__add_field { my $self = $_[0]; my $query = $self->{'query'}; $query->_add_field( 'time_start', 'simple' ); $self->assert( exists $query->{'_field_refs'}{'time_start'} ); $self->assert_deep_equals( [ { 'field' => 'time_start', 'alias' => undef, 'type' => 'simple' } ], $query->{'_fields'} ); $query->_add_field( 'count()', 'aggr', 'nrecords' ); $self->assert( exists $query->{'_field_refs'}{'nrecords'} ); $self->assert_deep_equals( [ { 'field' => 'time_start', 'alias' => undef, 'type' => 'simple' }, { 'field' => 'count()', 'alias' => 'nrecords', 'type' => 'aggr' } ], $query->{'_fields'} ); } sub test__add_field_bad_params { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_dies( qr/missing 'field' parameter/, sub { $query->_add_field() } ); $self->assert_dies( qr/missing 'type' parameter/, sub { $query->_add_field( 'a_field' ) } ); $self->assert_dies( qr/field name should contain only alphanumeric characters: 'a field'/, sub { $query->_add_field( 'a field', 'simple' ) } ); $self->assert_dies( qr/field name should contain only alphanumeric characters: 'sum\(\)'/, sub { $query->_add_field( 'sum()', 'aggr' ) } ); $self->assert_dies( qr/type should be 'simple', 'group', 'aggr': 'zoinzoin'/, sub { $query->_add_field( 'wawa', 'zoinzoin' ) } ); $self->assert_dies( qr/no field 'wawa' in 'test' schema/, sub { $query->_add_field( 'wawa', 'simple' ) } ); $self->assert_dies( qr/'nrecords' is already defined in the query/, sub { $query->_add_field( 'sum()', 'aggr', 'nrecords' ); $query->_add_field( 'sum()', 'aggr', 'nrecords' ) } ); } sub test__add_field_with_nested_query { my $self = $_[0]; my $query = $self->{'query'}; my $nested1 = $query->create_nested_query(); my $nested2 = $query->create_nested_query(); my $nested3 = $nested1->create_nested_query(); $query->_add_field( 'lr_timegroup(time_start)', 'group', 'period' ); $self->assert_dies( qr/'period' is already defined in the query/, sub { $nested1->_add_field( 'lr_timegroup(time_start)', 'group', 'period' ) } ); $self->assert_dies( qr/'period' is already defined in the query/, sub { $nested2->_add_field( 'lr_timegroup(time_start)', 'group', 'period' ) } ); $self->assert_dies( qr/'period' is already defined in the query/, sub { $nested3->_add_field( 'lr_timegroup(time_start)', 'group', 'period' ) } ); $nested1->_add_field( 'connection_id', 'simple' ); $self->assert_dies( qr/'connection_id' is already defined in the query/, sub { $query->_add_field( 'connection_id', 'simple' ) } ); $nested2->_add_field( 'connection_id', 'simple' ); $nested3->_add_field( 'file', 'simple' ); $self->assert_dies( qr/'file' is already defined in the query/, sub { $nested1->_add_field( 'file', 'simple' ) } ); } sub test_add_field { my $self = $_[0]; my $query = $self->{'query'}; $query->add_field( 'time_start' ); $self->assert_deep_equals( { 'field' => 'time_start', 'alias' => undef, 'type' => 'simple' }, $query->_field_by_name( 'time_start' ) ); $query->add_field( 'file', 'file_size/1024' ); $self->assert_deep_equals( { 'field' => 'file_size/1024', 'alias' => 'file', 'type' => 'simple' }, $query->_field_by_name( 'file' ) ); } sub test_add_field_after_add_group { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'connection_id' ); $self->assert_dies( qr/calls to add_field\(\) and add_group_field\(\) can't be mixed on the same Lire::DlfQuery/, sub { $query->add_field( 'file' ) } ); } sub test_add_field_with_create_nested_query { my $self = $_[0]; my $query = $self->{'query'}; my $nested = $query->create_nested_query(); $self->assert_dies( qr/can't add simple field to a query containing nested queries/, sub { $query->add_field( 'file' ) } ); $nested->add_field( 'file' ); $self->assert( defined $nested->_field_by_name( "file" ), "field 'file' wasn't added" ); } sub test_no_subqueries_on_simple_queries { my $self = $_[0]; my $query = $self->{'query'}; $query->add_field( 'file' ); $self->assert_dies( qr/can't create a nested query on query containing simple fields/, sub { $query->create_nested_query() } ); } sub test__fields_of_type { my $self = $_[0]; my $query = $self->{'query'}; $query->add_field( 'connection_id' ); $self->assert_deep_equals( [ { 'field' => 'connection_id', 'type' => 'simple', 'alias' => undef } ], $query->_fields_of_type('simple') ); $self->assert_deep_equals( [], $query->_fields_of_type('group+aggr') ); $self->assert_deep_equals( [ ], $query->_fields_of_type('group') ); $self->assert_deep_equals( [ ], $query->_fields_of_type('aggr') ); } sub test__fields_of_type_group { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'connection_id' ); $self->assert_deep_equals( [ { 'field' => 'connection_id', 'type' => 'group', 'alias' => undef } ], $query->_fields_of_type('group') ); } sub test__fields_of_type_group_aggr { my $self = $_[0]; my $query = $self->{'query'}; $query->add_aggr_field( 'nrecords', 'count(*)' ); $query->add_group_field( 'connection_id' ); $self->assert_deep_equals( [ { 'field' => 'count(*)', 'type' => 'aggr', 'alias' => 'nrecords' }, { 'field' => 'connection_id', 'type' => 'group', 'alias' => undef }, ], $query->_fields_of_type('group+aggr') ); } sub test__fields_of_type_bad_params { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_dies( qr/type should be 'simple', 'group', 'aggr' or 'group\+aggr': 'nosuchtype/, sub { $query->_fields_of_type('nosuchtype') } ); } sub test_add_group_field { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'connection_id' ); $self->assert_deep_equals( { 'field' => 'connection_id', 'alias' => undef, 'type' => 'group' }, $query->_field_by_name( 'connection_id' ) ); $query->add_group_field( 'period', 'lr_timegroup(time_start)' ); $self->assert_deep_equals( { 'field' => 'lr_timegroup(time_start)', 'alias' => 'period', 'type' => 'group' }, $query->_field_by_name( 'period' ) ); } sub test_group_fields { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_deep_equals( [], $query->group_fields() ); $query->add_group_field( 'period', 'lr_timegroup(time_start)' ); my $nested = $query->create_nested_query(); $nested->add_group_field( 'connection_id' ); $nested->add_aggr_field( 'nrecords', 'count()' ); $self->assert_deep_equals( ['period' ], $query->group_fields() ); $self->assert_deep_equals( ['period', 'connection_id' ], $nested->group_fields() ); } sub test_aggr_fields { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_deep_equals( [], $query->aggr_fields() ); $query->add_group_field( 'connection_id' ); $query->add_aggr_field( 'bytes', 'sum(file_size)' ); my $nested = $query->create_nested_query(); $nested->add_aggr_field( 'nrecords', 'count()' ); $self->assert_deep_equals( [ 'bytes', 'nrecords' ], $query->aggr_fields() ); $self->assert_deep_equals( [ 'nrecords' ], $nested->aggr_fields() ); } sub test_fields { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_deep_equals( [], $query->fields() ); $query->add_field( 'connection_id' ); $query->add_field( 'k', 'file_size/1024' ); $self->assert_deep_equals( [ 'connection_id', 'k' ], $query->fields() ); } sub test_field_def { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'connection_id' ); my $nested1 = $self->{'query'}->create_nested_query(); $nested1->add_aggr_field( 'nrecords', 'count()' ); my $nested2 = $self->{'query'}->create_nested_query(); $nested2->add_field( 'user' ); $nested2->add_field( 'file' ); $self->assert_dies( qr/no field 'time_start' defined in the query/, sub { $query->field_def( 'time_start' ) } ); $self->assert_str_equals( 'user', $query->field_def( 'user' ) ); $self->assert_str_equals( 'file', $query->field_def( 'file' ) ); $self->assert_str_equals( 'connection_id', $query->field_def( 'connection_id' ) ); $self->assert_str_equals( 'count()', $query->field_def( 'nrecords' ) ); $self->assert_dies( qr/no field 'file' defined in the query/, sub { $nested1->field_def( 'file' ) } ); $self->assert_str_equals( 'connection_id', $nested1->field_def( 'connection_id' ) ); $self->assert_str_equals( 'count()', $nested1->field_def( 'nrecords' ) ); $self->assert_dies( qr/no field 'nrecords' defined in the query/, sub { $nested2->field_def( 'nrecords' ) } ); $self->assert_str_equals( 'connection_id', $nested2->field_def( 'connection_id' ) ); $self->assert_str_equals( 'user', $nested2->field_def( 'user' ) ); $self->assert_str_equals( 'file', $nested2->field_def( 'file' ) ); } sub test__query_subtree_from_root { my $self = $_[0]; my $query = $self->{'query'}; my $nested1 = $query->create_nested_query(); my $nested2 = $query->create_nested_query(); my $nested3 = $nested1->create_nested_query(); $self->assert_deep_equals( [ $query, $nested1, $nested3, $nested2 ], $query->_query_subtree_from_root() ); $self->assert_deep_equals( [ $query, $nested1, $nested3 ], $nested1->_query_subtree_from_root() ); $self->assert_deep_equals( [ $query, $nested2 ], $nested2->_query_subtree_from_root() ); $self->assert_deep_equals( [ $query, $nested1, $nested3 ], $nested3->_query_subtree_from_root() ); } sub test_add_group_after_add_field { my $self = $_[0]; my $query = $self->{'query'}; $query->add_field( 'file' ); $self->assert_dies( qr/calls to add_field\(\) and add_group_field\(\) can't be mixed on the same Lire::DlfQuery/, sub { $query->add_group_field( 'connection_id' ) } ); } sub test_add_aggr_field { my $self = $_[0]; my $query = $self->{'query'}; $query->add_aggr_field( "requests", "count()" ); $self->assert_str_equals( 'aggr', $query->_field_by_name( 'requests' )->{'type'} ); $self->assert_dies( qr/missing 'aggregate' parameter/, sub { $query->add_aggr_field( "requests" ) } ); } sub test_set_sort_spec { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'time_start' ); $query->add_group_field( 'connection_id' ); $query->add_group_field( 'transfer-complete' ); my $nested = $query->create_nested_query(); $nested->add_aggr_field( 'downloads', "count()" ); $query->set_sort_spec( '-time_start' ); $self->assert_str_equals( '-time_start', $query->{'_sort_spec'} ); $self->assert_str_equals( 'time_start DESC', $query->{'_order_by'} ); $query->set_sort_spec( undef ); $self->assert_null( $query->{'_sort_spec'}, "'_sort_spec' attribute should have been cleared" ); $self->assert_null( $query->{'_order_by'}, "'_order_by' attribute should have been cleared" ); $query->set_sort_spec( '' ); $self->assert_null( $query->{'_sort_spec'}, "'_sort_spec' attribute should still be cleared" ); $self->assert_null( $query->{'_order_by'}, "'_order_by' attribute should still be cleared" ); $query->set_sort_spec( 'connection_id -time_start' ); $self->assert_str_equals( 'connection_id -time_start', $query->{'_sort_spec'} ); $self->assert_str_equals( 'connection_id, time_start DESC', $query->{'_order_by'} ); $query->set_sort_spec( 'transfer-complete' ); $self->assert_str_equals( '"transfer-complete"', $query->{'_order_by'} ); $query->set_sort_spec( '-transfer-complete' ); $self->assert_str_equals( '"transfer-complete" DESC', $query->{'_order_by'} ); $query->set_sort_spec( '-downloads' ); $self->assert_str_equals( 'downloads DESC', $query->{'_order_by'} ); $self->assert_dies( qr/field 'bad_field' unavailable for sorting/, sub { $query->set_sort_spec( 'bad_field' ); } ); } sub test__is_valid_sort_field { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'connection_id' ); my $nested1 = $query->create_nested_query(); $nested1->add_aggr_field( 'downloads', "count()" ); my $nested2 = $nested1->create_nested_query(); $nested2->add_field( 'user' ); $self->assert_num_equals( 0, $query->_is_valid_sort_field( 'bad_field' ) ); $self->assert_num_equals( 0, $query->_is_valid_sort_field( 'user' ) ); $self->assert_num_equals( 1, $query->_is_valid_sort_field( 'connection_id')); $self->assert_num_equals( 1, $query->_is_valid_sort_field( 'downloads')); $self->assert_num_equals( 0, $nested1->_is_valid_sort_field( 'bad_field' ) ); $self->assert_num_equals( 0, $nested1->_is_valid_sort_field( 'user' ) ); $self->assert_num_equals( 1, $nested1->_is_valid_sort_field( 'connection_id')); $self->assert_num_equals( 1, $nested1->_is_valid_sort_field( 'downloads')); $self->assert_num_equals( 0, $nested2->_is_valid_sort_field( 'bad_field' ) ); $self->assert_num_equals( 0, $nested2->_is_valid_sort_field( 'downloads')); $self->assert_num_equals( 1, $nested2->_is_valid_sort_field( 'user' ) ); $self->assert_num_equals( 1, $nested2->_is_valid_sort_field( 'connection_id')); } sub test_set_sort_spec_and_set_order_by_clause_interaction { my $self = $_[0]; my $query = $self->{'query'}; $query->add_field( 'time_start'); $query->set_sort_spec( 'time_start' ); $query->set_order_by_clause( 'connection_id' ); $self->assert_null( $query->{'_sort_spec'}, "'_sort_spec' attribute should have been cleared" ); } sub test_set_order_by_clause { my $self = $_[0]; my $query = $self->{'query'}; $query->set_order_by_clause( 'time_start DESC' ); $self->assert_str_equals( 'time_start DESC', $query->{'_order_by'} ); $query->set_order_by_clause( undef ); $self->assert_null( $query->{'_order_by'}, "order_by attribute should have been cleared" ); $query->set_order_by_clause( '' ); $self->assert_null( $query->{'_order_by'}, "order_by attribute should still be cleared" ); } sub test_set_limit { my $self = $_[0]; my $query = $self->{'query'}; $query->set_limit( 50 ); $self->assert_num_equals( 50, $query->{'_limit'} ); $query->set_limit( undef ); $self->assert_num_equals( 0, $query->{'_limit'} ); $query->set_limit( 20 ); $query->set_limit( 0 ); $self->assert_num_equals( 0, $query->{'_limit'} ); $self->assert_dies( qr/'limit' parameter should be an integer: 'some text'/, sub { $query->set_limit( 'some text' ) } ); } sub test_set_filter_clause { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_dies( qr/invalid number of parameters: filter clause contains 0 placeholders while 1 values provided/, sub { $query->set_filter_clause( undef, '' ); } ); $self->assert_dies( qr/invalid number of parameters: filter clause contains 1 placeholders while 0 values provided/, sub { $query->set_filter_clause( 'time_start > ?' ); } ); $self->assert_dies( qr/invalid number of parameters: filter clause contains 1 placeholders while 2 values provided/, sub { $query->set_filter_clause( 'time_start > ?', 1, 2 ); } ); $query->set_filter_clause( 'time_start = 0' ); $self->assert_str_equals( 'time_start = 0', $query->{'_filter_clause'} ); $self->assert_deep_equals( [], $query->{'_filter_params'}); $query->set_filter_clause( 'time_start > ?', 0 ); $self->assert_str_equals( 'time_start > ?', $query->{'_filter_clause'} ); $self->assert_deep_equals( [ 0 ], $query->{'_filter_params'}); $query->set_filter_clause( undef ); $self->assert_null( $query->{'_filter_clause'}, "filter_clause attribute should have been cleared" ); $self->assert_deep_equals( [], $query->{'_filter_params'}); $query->set_filter_clause( '' ); $self->assert_null( $query->{'_filter_clause'}, "filter_clause attribute should still be cleared" ); $self->assert_deep_equals( [], $query->{'_filter_params'}); } sub test_sql_params { my $self = $_[0]; my $query = $self->{'query'}; $query->set_filter_clause( 'time_start = 0' ); $self->assert_deep_equals( [], $query->sql_params() ); $query->set_filter_clause( 'time_start = ?', '12345678' ); $self->assert_deep_equals( [ '12345678' ], $query->sql_params() ); my $nested = $query->create_nested_query(); $nested->set_filter_clause( 'user IN ?', "( 'wdankers', 'flacoste' )" ); $self->assert_deep_equals( [ '12345678', "( 'wdankers', 'flacoste' )"], $nested->sql_params() ); my $nested2 = $nested->create_nested_query(); $nested2->set_filter_clause( 'file LIKE ? ', "%.mpg" ); $self->assert_deep_equals( [ '12345678', "( 'wdankers', 'flacoste' )", '%.mpg' ], $nested2->sql_params() ); } sub test_join_stream { my $self = $_[0]; $self->assert_deep_equals( [], $self->{'query'}{'_joined_streams'} ); $self->assert_dies( qr/there is no schema: 'bad_schema'/, sub { $self->{'query'}->join_stream( 'bad_schema' ) } ); $self->assert_dies( qr/cannot join 'test-derived' with 'test'/, sub { $self->{'query'}->join_stream( 'test-derived') } ); my $nested = $self->{'query'}->create_nested_query(); $self->assert_dies( qr/can only join streams on root query/, sub { $nested->join_stream( 'test-extended' ) } ); $self->{'query'}->join_stream( 'test-extended' ); $self->assert_deep_equals( [ 'test-extended' ], $self->{'query'}{'_joined_streams'} ); $self->assert_deep_equals( [ 'test', 'test-extended' ], $self->{'query'}->joined_streams() ); $self->assert_dies( qr/'test-extended' is already joined/, sub { $self->{'query'}->join_stream( 'test-extended' )}); my $query = new Lire::DlfQuery( 'test-extended' ); $self->assert_dies( qr/'test-extended' is already joined/, sub { $query->join_stream( 'test-extended' )}); } sub test_execute { my $self = $_[0]; $self->set_up_test_store(); my $query = $self->{'query'}; $query->add_field( 'user' ); $query->add_field( 'file' ); $self->assert_dies( qr/missing 'store' parameter/, sub { $query->execute () } ); my $result = $query->execute( $self->{'store'} ); $self->assert_isa( 'Lire::DlfResult', $result ); } sub test_execute_summary { my $self = $_[0]; $self->set_up_test_store(); my $query = $self->{'query'}; $query->add_group_field( 'user' ); $query->add_aggr_field( 'downloads', 'count()' ); $self->assert_dies( qr/missing 'store' parameter/, sub { $query->execute_summary () } ); my $result = $query->execute_summary( $self->{'store'} ); $self->assert_isa( 'Lire::DlfResult', $result ); my $summary = $result->next_row(); $self->assert( ! $result->next_row(), "only one row should be returned by summary on top-level query" ); } sub test_execute_no_stream { my $self = $_[0]; $self->set_up_test_store(); my $query = new Lire::DlfQuery( 'test' ); $query->{'_joined_streams'} = [ 'test-extended' ]; $self->assert_dies( qr/store doesn't contain a 'test-extended' stream/, sub { $query->execute_summary( $self->{'store'} ) } ); $self->assert_dies( qr/store doesn't contain a 'test-extended' stream/, sub { $query->execute( $self->{'store'} ) } ); } sub test__sql_select_clause_quoting { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( "connection_id" ); $query->add_group_field( "transfer-complete" ); $query->add_group_field( "total-requests", "count()" ); $query->add_group_field( "period", "lr_timegroup(time_start)" ); $self->assert_str_equals( <<ESQL, $query->_sql_select_clause() . "\n"); SELECT connection_id, "transfer-complete", count() AS "total-requests", lr_timegroup(time_start) AS period ESQL } sub test__sql_from_clause { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_str_equals( "FROM dlf_test", $query->_sql_from_clause() ); $query->{'_stream_name'} = "test-extended"; $self->assert_str_equals( 'FROM dlf_test, "dlf_test-extended"', $query->_sql_from_clause() ); $query->{'_stream_name'} = 'test'; $query->{'_joined_streams'} = [ "test-extended" ]; $self->assert_str_equals( 'FROM dlf_test, "dlf_test-extended"', $query->_sql_from_clause() ); $query->{'_stream_name'} = 'test-derived'; $query->{'_joined_streams'} = [ "test-extended" ]; $self->assert_str_equals( 'FROM "dlf_test-derived", "dlf_test-derived_links", "dlf_test-extended"', $query->_sql_from_clause() ); $query->{'_joined_streams'} = [ "test" ]; $self->assert_str_equals( 'FROM "dlf_test-derived", "dlf_test-derived_links", dlf_test', $query->_sql_from_clause() ); $query->{'_joined_streams'} = []; $self->assert_str_equals( 'FROM "dlf_test-derived"', $query->_sql_from_clause() ); $query->{'_joined_streams'} = [ 'test-extended2' ]; $self->assert_str_equals( 'FROM "dlf_test-derived", "dlf_test-extended2"', $query->_sql_from_clause() ); } sub test__sql_group_by_clause_quoting { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( "connection_id" ); $query->add_group_field( "transfer-complete" ); $query->add_group_field( "total-requests", "count()" ); $query->add_group_field( "period", "lr_timegroup(time_start)" ); $self->assert_str_equals( q{GROUP BY connection_id, "transfer-complete", "total-requests", period}, $query->_sql_group_by_clause() ); } sub test__as_sql { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'period', 'lr_timegroup(time_start)' ); $query->add_group_field( 'client_host' ); $query->add_aggr_field( 'requests', 'count()' ); $query->add_aggr_field( 'bytes', 'sum(file_size)' ); $query->set_order_by_clause( "period, bytes DESC" ); $query->set_filter_clause( "file = ?", "index.html" ); $query->set_limit( 5 ); $self->assert_str_equals ( <<SQLS, $query->_as_sql() ); SELECT lr_timegroup(time_start) AS period, client_host, count() AS requests, sum(file_size) AS bytes FROM dlf_test WHERE file = ? GROUP BY period, client_host ORDER BY period, bytes DESC LIMIT 5 SQLS } sub test__sql_select_fields { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'file' ); my $nquery1 = $query->create_nested_query(); $nquery1->add_group_field( 'connection_id' ); $nquery1->add_aggr_field( 'bytes', 'sum(file_size)' ); my $nquery2 = $query->create_nested_query(); $nquery2->add_aggr_field( 'requests', 'count(*)' ); $nquery2->add_field( 'connection_id' ); $self->assert_deep_equals( [ { 'field' => 'file', 'type' => 'group', 'alias' => undef }, { 'field' => 'sum(file_size)', 'type' => 'aggr', 'alias' => 'bytes' }, { 'field' => 'count(*)', 'type' => 'aggr', 'alias' => 'requests' }, ], $query->_sql_select_fields() ); $self->assert_deep_equals( [ { 'field' => 'sum(file_size)', 'type' => 'aggr', 'alias' => 'bytes' }, { 'field' => 'count(*)', 'type' => 'aggr', 'alias' => 'requests' }, ], $query->_sql_select_fields( 1 ) ); $self->assert_deep_equals( [ { 'field' => 'connection_id', 'type' => 'simple', 'alias' => undef }, ], $nquery2->_sql_select_fields() ); $self->assert_deep_equals( [ { 'field' => 'count(*)', 'type' => 'aggr', 'alias' => 'requests' }, ], $nquery2->_sql_select_fields(1) ); } sub test__sql_where_clause { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_null( $query->_sql_where_clause() ); $query->{'_filter_clause'} = 'time_stamp = ?'; $self->assert_str_equals( 'WHERE time_stamp = ?', $query->_sql_where_clause() ); my $sub = $query->create_nested_query(); $self->assert_str_equals( 'WHERE time_stamp = ?', $sub->_sql_where_clause() ); $sub->{'_filter_clause'} = 'connection_id LIKE ?'; $self->assert_str_equals( 'WHERE time_stamp = ?', $query->_sql_where_clause() ); $self->assert_str_equals( 'WHERE time_stamp = ? AND connection_id LIKE ?', $sub->_sql_where_clause() ); $query->{'_stream_name'} = 'test-extended'; $self->assert_str_equals( 'WHERE dlf_test.dlf_id = "dlf_test-extended".dlf_id AND time_stamp = ?', $query->_sql_where_clause() ); } sub test__sql_where_join_elements { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_deep_equals( [], $query->_sql_where_join_elements() ); $query->{'_stream_name'} = 'test-extended'; $self->assert_deep_equals( [ 'dlf_test.dlf_id = "dlf_test-extended".dlf_id' ], $query->_sql_where_join_elements() ); $query->{'_stream_name'} = 'test'; $query->{'_joined_streams'} = [ 'test-extended' ]; $self->assert_deep_equals( [ 'dlf_test.dlf_id = "dlf_test-extended".dlf_id' ], $query->_sql_where_join_elements() ); $query->{'_stream_name'} = 'test-derived'; $query->{'_joined_streams'} = [ 'test', 'test-extended', 'test-extended2' ]; $self->assert_deep_equals( [ '"dlf_test-derived".dlf_id = "dlf_test-derived_links".src_id', '"dlf_test-derived_links".link_id = dlf_test.dlf_id', '"dlf_test-derived_links".link_id = "dlf_test-extended".dlf_id', '"dlf_test-derived".dlf_id = "dlf_test-extended2".dlf_id' ], $query->_sql_where_join_elements() ); $query->{'_joined_streams'} = [ 'test-extended2' ]; $self->assert_deep_equals( [ '"dlf_test-derived".dlf_id = "dlf_test-extended2".dlf_id' ], $query->_sql_where_join_elements() ); } sub test__as_sql_with_nested_query { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'period', 'lr_timegroup(time_start)' ); $query->add_aggr_field( 'nrecords', 'count()' ); $query->set_filter_clause( 'time_start > ?', "123456789" ); $query->set_order_by_clause( "period" ); my $nquery1 = $query->create_nested_query(); $nquery1->add_group_field( 'connection_id' ); $nquery1->add_aggr_field( 'bytes', 'sum(file_size)' ); $nquery1->set_order_by_clause( "bytes DESC" ); my $nquery2 = $query->create_nested_query(); $nquery2->add_group_field( "file" ); $nquery2->add_aggr_field( "downloads", "count()" ); $nquery2->set_filter_clause( 'file = ?', "index.html" ); $self->assert_str_equals( <<SQLS, $query->_as_sql() ); SELECT lr_timegroup(time_start) AS period, count() AS nrecords, sum(file_size) AS bytes, count() AS downloads FROM dlf_test WHERE time_start > ? GROUP BY period ORDER BY period SQLS $self->assert_str_equals( <<SQLS, $nquery1->_as_sql() ); SELECT lr_timegroup(time_start) AS period, connection_id, sum(file_size) AS bytes FROM dlf_test WHERE time_start > ? GROUP BY period, connection_id ORDER BY period, bytes DESC SQLS $self->assert_str_equals( <<SQLS, $nquery2->_as_sql() ); SELECT lr_timegroup(time_start) AS period, file, count() AS downloads FROM dlf_test WHERE time_start > ? AND file = ? GROUP BY period, file ORDER BY period SQLS } sub test__as_sql_select_only { my $self = $_[0]; my $query = $self->{'query'}; $query->add_field( 'requests', 'count()' ); $query->add_field( 'bytes', 'sum(file_size)' ); $self->assert_str_equals ( <<SQLS, $query->_as_sql() ); SELECT count() AS requests, sum(file_size) AS bytes FROM dlf_test SQLS } sub test__as_summary_sql { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'period', 'lr_timegroup(time_start)' ); $query->add_group_field( 'client_host' ); $query->add_aggr_field( 'requests', 'count()' ); $query->add_aggr_field( 'bytes', 'sum(file_size)' ); $query->set_order_by_clause( "period, bytes DESC" ); $query->set_filter_clause( "file = ?", "index.html" ); $query->set_limit( 5 ); $self->assert_str_equals ( <<SQLS, $query->_as_summary_sql() ); SELECT count() AS requests, sum(file_size) AS bytes FROM dlf_test WHERE file = ? SQLS } sub test__as_summary_sql_nested_query { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'period', 'lr_timegroup(time_start)' ); $query->add_aggr_field( 'nrecords', 'count()' ); $query->set_filter_clause( 'time_start > ?', 123456789 ); $query->set_order_by_clause( "period" ); my $nquery1 = $query->create_nested_query(); $nquery1->add_group_field( 'connection_id' ); $nquery1->add_aggr_field( 'bytes', 'sum(file_size)' ); $nquery1->set_order_by_clause( "bytes DESC" ); my $nquery2 = $query->create_nested_query(); $nquery2->add_group_field( "file" ); $nquery2->add_aggr_field( "downloads", "count()" ); $nquery2->set_filter_clause( 'file = ?', "index.html" ); $self->assert_str_equals( <<SQLS, $query->_as_summary_sql() ); SELECT count() AS nrecords, sum(file_size) AS bytes, count() AS downloads FROM dlf_test WHERE time_start > ? SQLS $self->assert_str_equals( <<SQLS, $nquery1->_as_summary_sql() ); SELECT lr_timegroup(time_start) AS period, sum(file_size) AS bytes FROM dlf_test WHERE time_start > ? GROUP BY period ORDER BY period SQLS $self->assert_str_equals( <<SQLS, $nquery2->_as_summary_sql() ); SELECT lr_timegroup(time_start) AS period, count() AS downloads FROM dlf_test WHERE time_start > ? AND file = ? GROUP BY period ORDER BY period SQLS } sub test__as_summary_sql_no_where { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'period', 'lr_timegroup(time_start)' ); $query->add_group_field( 'client_host' ); $query->add_aggr_field( 'requests', 'count()' ); $query->add_aggr_field( 'bytes', 'sum(file_size)' ); $query->set_order_by_clause( "period, bytes DESC" ); $query->set_limit( 5 ); $self->assert_str_equals ( <<SQLS, $query->_as_summary_sql() ); SELECT count() AS requests, sum(file_size) AS bytes FROM dlf_test SQLS } sub test__as_sql_simple_field_nested_query { my $self = $_[0]; my $query = $self->{'query'}; $query->add_group_field( 'period', 'lr_timegroup(time_start)' ); $query->set_order_by_clause( 'period' ); my $nquery = $query->create_nested_query(); $nquery->add_field( 'time_start' ); $nquery->add_field( 'user' ); $nquery->add_field( 'file' ); $nquery->add_field( 'time_taken' ); $self->assert_str_equals ( <<SQLS, $nquery->_as_sql() ); SELECT lr_timegroup(time_start) AS period, time_start, user, file, time_taken FROM dlf_test ORDER BY period SQLS } sub test_create_nested_query { my $self = $_[0]; my $query = $self->{'query'}; $self->assert_null( $query->{'_parent'}, "new query should have NULL parent" ); $self->assert_deep_equals( [], $query->{'_nested_queries'} ); my $nested = $self->{'query'}->create_nested_query(); $self->assert_isa( 'Lire::DlfQuery', $nested ); $self->assert_str_equals( $query->{'_stream_name'}, $nested->{'_stream_name'} ); $self->assert_str_equals( $query, $nested->{'_parent'} ); $self->assert_deep_equals( [ $nested ], $query->{'_nested_queries'} ); } sub test_release { my $self = $_[0]; my $query = $self->{'query'}; my $nested = $query->create_nested_query(); $query->release(); $self->assert_null( $nested->{'_parent'}, "_parent attribute of nested queries should be undef" ); } sub test__root_query { my $self = $_[0]; $self->assert_str_equals( $self->{'query'}, $self->{'query'}->_root_query() ); my $nested = $self->{'query'}->create_nested_query(); $self->assert_str_equals( $self->{'query'}, $nested->_root_query() ); my $nested2 = $nested->create_nested_query(); $self->assert_str_equals( $self->{'query'}, $nested2->_root_query() ); } sub test__sql_order_by_clause { my $self = $_[0]; my $query = $self->{'query'}; my $clause = $query->_sql_order_by_clause(); $self->assert_null( $clause, '_sql_order_by_clause() should be undef' ); $query->{'_order_by'} = 'connection_id, user'; $self->assert_str_equals( 'ORDER BY connection_id, user', $query->_sql_order_by_clause() ); my $squery = $query->create_nested_query(); $self->assert_str_equals( 'ORDER BY connection_id, user', $squery->_sql_order_by_clause() ); $squery->{'_order_by'} = 'file DESC'; $self->assert_str_equals( 'ORDER BY connection_id, user, file DESC', $squery->_sql_order_by_clause() ); $query->{'_order_by'} = undef; $self->assert_str_equals( 'ORDER BY file DESC', $squery->_sql_order_by_clause() ); } 1; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/����������������������������������������������������������������������0000755�0001750�0001750�00000000000�11677607770�013062� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-empty-merge.xml��������������������������������������������������0000644�0001750�0001750�00000036645�10460672600�016731� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="us-ascii"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "http://www.logreport.org/LRML/2.1/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" version="2.1"> <!-- generated by Lire::Report(3pm) --> <lire:date time="1067361273">2003-10-28 12:14:33 EST</lire:date> <lire:timespan start="" end="">Unknown Period</lire:timespan> <lire:section> <lire:title>All Files</lire:title> <lire:subreport type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="4" label="File" max-chars="4" avg-chars="4"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="5"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="request_total" missing-cases="0">0</lire:value> <lire:value col="request_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> <lire:subreport type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="9"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0">0</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> <lire:subreport type="downloads-by-period" superservice="test" schemas="test"> <lire:title>Download by 15m Period</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timegroup:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="6" label="Period" max-chars="6" avg-chars="6"/> <lire:column-info name="download_count" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="5"/> <lire:column-info name="download_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> <lire:column-info name="user_count" class="numerical" type="int" col-start="3" col-end="3" col-width="12" label="Unique Users" max-chars="12" avg-chars="7"/> <lire:column-info name="user_ratio" class="numerical" type="int" col-start="4" col-end="4" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">NaN</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>JPEG Files</lire:title> <lire:description><para>Applied filter in this section: selected files matching .*.jpg$</para> </lire:description> <lire:subreport type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="4" label="File" max-chars="4" avg-chars="4"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="5"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="request_total" missing-cases="0">0</lire:value> <lire:value col="request_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> <lire:subreport type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="9"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0">0</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Sessions</lire:title> <lire:subreport type="sessions-by-length" superservice="test" schemas="test-derived"> <lire:title>Sessions by Length</lire:title> <lire:table> <lire:table-info> <lire:column-info name="rangegroup:session_length" class="categorical" type="duration" col-start="0" col-end="0" col-width="6" label="Length" max-chars="6" avg-chars="6"/> <lire:column-info name="sessions_count" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="5"/> <lire:column-info name="sessions_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> <lire:subreport type="sessions-by-user_class" superservice="test" schemas="test-derived"> <lire:title>Sessions by User Class</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user_class" class="categorical" type="string" col-start="0" col-end="0" col-width="10" label="user_class" max-chars="10" avg-chars="10"/> <lire:column-info name="sessions_total" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="sessions_total" missing-cases="0">0</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Download Reports</lire:title> <lire:subreport type="avg-file_size-by-timeslot" superservice="test" schemas="test"> <lire:title>Average File Size By 1h Timeslot</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timeslot:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="6" label="Length" max-chars="6" avg-chars="6"/> <lire:column-info name="avg_file_size" class="numerical" type="bytes" col-start="1" col-end="1" col-width="13" label="Avg File Size" max-chars="13" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timeslot:time_start" value="2-0" range="1">00:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timeslot:time_start" value="2-1" range="1">01:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="timeslot:time_start" value="2-2" range="1">02:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="timeslot:time_start" value="2-3" range="1">03:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="timeslot:time_start" value="2-4" range="1">04:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="5"> <lire:name col="timeslot:time_start" value="2-5" range="1">05:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="6"> <lire:name col="timeslot:time_start" value="2-6" range="1">06:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="7"> <lire:name col="timeslot:time_start" value="2-7" range="1">07:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="8"> <lire:name col="timeslot:time_start" value="2-8" range="1">08:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="9"> <lire:name col="timeslot:time_start" value="2-9" range="1">09:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="10"> <lire:name col="timeslot:time_start" value="2-10" range="1">10:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="11"> <lire:name col="timeslot:time_start" value="2-11" range="1">11:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="12"> <lire:name col="timeslot:time_start" value="2-12" range="1">12:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="13"> <lire:name col="timeslot:time_start" value="2-13" range="1">13:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="14"> <lire:name col="timeslot:time_start" value="2-14" range="1">14:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="15"> <lire:name col="timeslot:time_start" value="2-15" range="1">15:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="16"> <lire:name col="timeslot:time_start" value="2-16" range="1">16:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="17"> <lire:name col="timeslot:time_start" value="2-17" range="1">17:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="18"> <lire:name col="timeslot:time_start" value="2-18" range="1">18:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="19"> <lire:name col="timeslot:time_start" value="2-19" range="1">19:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="20"> <lire:name col="timeslot:time_start" value="2-20" range="1">20:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="21"> <lire:name col="timeslot:time_start" value="2-21" range="1">21:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="22"> <lire:name col="timeslot:time_start" value="2-22" range="1">22:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="23"> <lire:name col="timeslot:time_start" value="2-23" range="1">23:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="user_downloads-report" superservice="test" schemas="test"> <lire:title>User's Downloads Report</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user" class="categorical" type="string" col-start="0" col-end="3" col-width="2" label="Username" max-chars="8" avg-chars="8"/> <lire:column-info name="first_file" class="numerical" type="filename" col-start="4" col-end="4" col-width="10" label="First File" max-chars="10" avg-chars="5"/> <lire:column-info name="last_file" class="numerical" type="filename" col-start="5" col-end="5" col-width="9" label="Last File" max-chars="9" avg-chars="5"/> <lire:column-info name="min_file_size" class="numerical" type="bytes" col-start="6" col-end="6" col-width="8" label="Smallest" max-chars="8" avg-chars="6"/> <lire:column-info name="max_file_size" class="numerical" type="bytes" col-start="7" col-end="7" col-width="7" label="Largest" max-chars="7" avg-chars="5"/> <lire:group-info name="records:3" row-idx="1"> <lire:column-info name="time_start" class="categorical" type="timestamp" col-start="1" col-end="1" col-width="10" label="Start Time" max-chars="10" avg-chars="10"/> <lire:column-info name="file" class="categorical" type="filename" col-start="2" col-end="2" col-width="4" label="File" max-chars="4" avg-chars="4"/> <lire:column-info name="file_size" class="categorical" type="bytes" col-start="3" col-end="3" col-width="4" label="Size" max-chars="4" avg-chars="4"/> </lire:group-info> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="first_file" missing-cases="0" total=""></lire:value> <lire:value col="last_file" missing-cases="0" total=""></lire:value> <lire:value col="min_file_size" missing-cases="0">NaN</lire:value> <lire:value col="max_file_size" missing-cases="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> </lire:report> �������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-utf8-nosupport.xml�����������������������������������������������0000644�0001750�0001750�00000004044�10460672601�017420� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "http://www.logreport.org/LRML/2.1/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" version="2.1"> <!-- Généré la main par Francis et Wolfgang --> <lire:date time="1073666899">2004-01-09 11:48:19 EST</lire:date> <lire:timespan start="1043515006" end="1043516705">2003-01-25 12:16:46 EST - 2003-01-25 12:45:05 EST</lire:timespan> <lire:section> <lire:title>Telechargements</lire:title> <lire:subreport id="user-downloads-utf8.0" type="user-downloads-utf8" superservice="test" schemas="test"> <lire:title>Téléchargements par usager, Top 5 </lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="user" class="categorical" type="string" col-start="0" col-end="0" col-width="9" label="Usager" max-chars="9" avg-chars="8"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="15" label="Téléchargements" max-chars="15" avg-chars="5"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="4" missing-cases="0"> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="user">fran??ois</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">50.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="user">h??l??ne</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">50.0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> </lire:report> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/jobs-config-15.xml����������������������������������������������������0000644�0001750�0001750�00000006440�10460672600�016132� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE config PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Markup Language V1.0//EN" "http://www.logreport.org/LRCML/1.0/lrcml.dtd"[ <!ENTITY % LIRE.pfx ""> ]> <config xmlns="http://www.logreport.org/LRCML/"> <global> <param name="lr_week_numbering">ISO</param> <param name="streams_config"> <param name="test"> <param name="keep_days">1</param> <param name="test-extended" value="extended"> </param> <param name="test-derived" value="derived"> </param> </param> <param name="test-derived"> <param name="keep_days">60</param> <param name="test-extended" value="none"> </param> </param> <param name="test-extended" /> </param> <param name="report_jobs"> <param name="report_job"> <param name="name">Test_Report</param> <param name="schedules"> <param name="schedule"> <param name="output_jobs"> <param name="output_job"> <param name="format" value="pdf"> <param name="charts">1</param> </param> <param name="destination" value="email"> <param name="subject">PDF Report</param> <param name="emails"> <param name="email">flacoste@logreport.org</param> </param> </param> <param name="name">PDF</param> </param> </param> <param name="period">daily</param> <param name="report_cfg">test.cfg</param> </param> <param name="schedule"> <param name="output_jobs"> <param name="output_job"> <param name="format" value="html"> <param name="charts">1</param> <param name="one_page"></param> <param name="xhtml"></param> </param> <param name="destination" value="file"> <param name="file">report %Y-W%V</param> </param> <param name="name">HTML</param> </param> <param name="output_job"> <param name="format" value="txt"> <param name="encoding" /> </param> <param name="destination" value="email"> <param name="subject">Text Report</param> <param name="emails"> <param name="email">wolfgang@logreport.org</param> </param> </param> <param name="name">Text Email</param> </param> </param> <param name="period">weekly</param> <param name="report_cfg">test.cfg</param> </param> </param> <param name="superservice">test</param> </param> </param> <param name="import_jobs"> <param name="import_job"> <param name="period">daily</param> <param name="filter"></param> <param name="name">Daily Import</param> <param name="log_encoding"></param> <param name="log_file">test.dlf</param> <param name="service" value="test_newapi"> </param> </param> </param> </global> </config> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-utf8.dlf���������������������������������������������������������0000644�0001750�0001750�00000000757�10460672601�015325� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515006 1043515010 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 françois /pictures/000011.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515010 1043515013 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 françois /pictures/000012.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043516701 1043516705 LIRE_NOTAVAIL AABBCCDD 192.168.250.3 hélène /pictures/000010.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043516705 1043516715 LIRE_NOTAVAIL AABBCCDD 192.168.250.3 hélène /pictures/000011.jpg 26345 1 �����������������lire-2.1.1/all/lib/tests/data/test-utf8.xml���������������������������������������������������������0000644�0001750�0001750�00000004106�10460672601�015350� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "http://www.logreport.org/LRML/2.1/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" xmlns:lrcml="http://www.logreport.org/LRCML/" version="2.1"> <!-- generated by Lire::Report(3pm) --> <lire:date time="1093930249">2004-08-31 00:30:49 EST</lire:date> <lire:timespan start="1043515006" end="1043516705">2003-01-25 12:16:46 EST - 2003-01-25 12:45:05 EST</lire:timespan> <lire:section> <lire:title>Téléchargements</lire:title> <lire:subreport id="user-downloads-utf8.0" superservice="test" type="user-downloads-utf8" schemas='test'> <lire:title>Téléchargements par usager, Top 5 </lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="user" class="categorical" type="string" col-start="0" col-end="0" col-width="8" label="Usager" max-chars="8" avg-chars="7"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="15" label="Téléchargements" max-chars="15" avg-chars="5"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="4" missing-cases="0"> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="user">françois</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">50.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="user">hélène</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">50.0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> </lire:report> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-l10n.xml���������������������������������������������������������0000644�0001750�0001750�00000012775�10460672600�015246� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "http://www.logreport.org/LRML/2.1/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" xmlns:lrcml="http://www.logreport.org/LRCML/" version="2.1"> <!-- generated by Lire::Report(3pm) --> <lire:date time="1093927660">2004-08-30 23:47:40 EST</lire:date> <lire:timespan start="1043514000" end="1043526410">2003-01-25 12:00:00 EST - 2003-01-25 15:26:50 EST</lire:timespan> <lire:section> <lire:title>Fichiers JPEG</lire:title> <lire:description><para>Filtre appliqué à cette section: fichiers sélectionnés selon le patron .*.jpg$</para> </lire:description> <lire:subreport id="top-files.0" superservice="test" type="top-files" schemas='test'> <lire:title>Transferts par fichiers, les 5 les plus transférés</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="Fichier" max-chars="20" avg-chars="18"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="15" label="Téléchargements" max-chars="15" avg-chars="4"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="19" missing-cases="0"> <lire:value col="request_total" missing-cases="0">19</lire:value> <lire:value col="request_ratio" missing-cases="0" value="19">100,0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10,5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10,5</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10,5</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10,5</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10,5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10,5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10,5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5,3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5,3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5,3</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="top-dirs.0" superservice="test" type="top-dirs" schemas='test-extended'> <lire:title>Téléchargements par répertoire, les 5 avec le plus de transferts</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="10" label="Répertoire" max-chars="10" avg-chars="10"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="17" label="Octets transférés" max-chars="17" avg-chars="10"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% total" max-chars="7" avg-chars="6"/> </lire:table-info> <lire:group-summary nrecords="19" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0" value="507542">495,6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">100,0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" missing-cases="0" value="507542">495,6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">100,0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> </lire:report> ���lire-2.1.1/all/lib/tests/data/TestReport_weekly_w04_2003.xml����������������������������������������0000644�0001750�0001750�00000145404�10460672600�020344� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "http://www.logreport.org/LRML/2.1/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" xmlns:lrcml="http://www.logreport.org/LRCML/" version="2.1" > <!-- generated by Lire::Report(3pm) --> <lire:date time="1081356462">2004-04-07 11:47:42 EST</lire:date> <lire:timespan start="1043514000" end="1043526410">2003-01-25 12:00:00 EST - 2003-01-25 15:26:50 EST</lire:timespan> <lire:section> <lire:title>All Files</lire:title> <lire:subreport id="top-files.0" type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="File" max-chars="20" avg-chars="17"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="request_total" missing-cases="0">24</lire:value> <lire:value col="request_ratio" missing-cases="0" value="24">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:value col="request_total" missing-cases="0">3</lire:value> <lire:value col="request_ratio" missing-cases="0" value="3">12.5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">4.2</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">4.2</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="top-dirs.0" type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="8"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0" value="9037995">8.6M</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="9037995">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/movies</lire:name> <lire:value col="bytes_total" missing-cases="0" value="8530453">8.1M</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="8530453">94.4</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" missing-cases="0" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">5.6</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="downloads-by-period.0" type="downloads-by-period" superservice="test" schemas="test"> <lire:title>Download by 15m Period</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timegroup:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="16" label="Period" max-chars="16" avg-chars="16"/> <lire:column-info name="download_count" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="2"/> <lire:column-info name="download_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> <lire:column-info name="user_count" class="numerical" type="int" col-start="3" col-end="3" col-width="12" label="Unique Users" max-chars="12" avg-chars="2"/> <lire:column-info name="user_ratio" class="numerical" type="int" col-start="4" col-end="4" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="download_count" missing-cases="0">24</lire:value> <lire:value col="download_ratio" missing-cases="0" value="24">100.0</lire:value> <lire:value col="user_count" missing-cases="0">5</lire:value> <lire:value col="user_ratio" missing-cases="0" value="5">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timegroup:time_start" value="1043514000" range="900">2003-01-25 12:00</lire:name> <lire:value col="download_count" missing-cases="0">4</lire:value> <lire:value col="download_ratio" missing-cases="0" value="4">16.7</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timegroup:time_start" value="1043514900" range="900"> 12:15</lire:name> <lire:value col="download_count" missing-cases="0">11</lire:value> <lire:value col="download_ratio" missing-cases="0" value="11">45.8</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="timegroup:time_start" value="1043515800" range="900"> 12:30</lire:name> <lire:value col="download_count" missing-cases="0">6</lire:value> <lire:value col="download_ratio" missing-cases="0" value="6">25.0</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="timegroup:time_start" value="1043516700" range="900"> 12:45</lire:name> <lire:value col="download_count" missing-cases="0">2</lire:value> <lire:value col="download_ratio" missing-cases="0" value="2">8.3</lire:value> <lire:value col="user_count" missing-cases="0">1</lire:value> <lire:value col="user_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="timegroup:time_start" value="1043517600" range="900"> 13:00</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="5"> <lire:name col="timegroup:time_start" value="1043518500" range="900"> 13:15</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="6"> <lire:name col="timegroup:time_start" value="1043519400" range="900"> 13:30</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="7"> <lire:name col="timegroup:time_start" value="1043520300" range="900"> 13:45</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="8"> <lire:name col="timegroup:time_start" value="1043521200" range="900"> 14:00</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="9"> <lire:name col="timegroup:time_start" value="1043522100" range="900"> 14:15</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="10"> <lire:name col="timegroup:time_start" value="1043523000" range="900"> 14:30</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="11"> <lire:name col="timegroup:time_start" value="1043523900" range="900"> 14:45</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="12"> <lire:name col="timegroup:time_start" value="1043524800" range="900"> 15:00</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="13"> <lire:name col="timegroup:time_start" value="1043525700" range="900"> 15:15</lire:name> <lire:value col="download_count" missing-cases="0">1</lire:value> <lire:value col="download_ratio" missing-cases="0" value="1">4.2</lire:value> <lire:value col="user_count" missing-cases="0">1</lire:value> <lire:value col="user_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> </lire:table> <lire:chart-configs> <lrcml:param name="chart"> <lrcml:param name="title" value="Users and Downloads by 15m" /> <lrcml:param name="case_var" value="timegroup:time_start" /> <lrcml:param name="type" value="vbars"> <lrcml:param name="y" value="download_count" /> <lrcml:param name="y2" value="user_count" /> </lrcml:param> </lrcml:param> </lire:chart-configs> </lire:subreport> </lire:section> <lire:section> <lire:title>JPEG Files</lire:title> <lire:description><para>Applied filter in this section: selected files matching .*.jpg$</para> </lire:description> <lire:subreport id="top-files.1" type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="File" max-chars="20" avg-chars="18"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="19" missing-cases="0"> <lire:value col="request_total" missing-cases="0">19</lire:value> <lire:value col="request_ratio" missing-cases="0" value="19">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5.3</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="top-dirs.1" type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="10"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="6"/> </lire:table-info> <lire:group-summary nrecords="19" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" missing-cases="0" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">100.0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Sessions</lire:title> <lire:subreport id="sessions-by-length.0" type="sessions-by-length" superservice="test" schemas="test-derived"> <lire:title>Sessions by Length</lire:title> <lire:table> <lire:table-info> <lire:column-info name="rangegroup:session_length" class="categorical" type="duration" col-start="0" col-end="0" col-width="9" label="Length" max-chars="9" avg-chars="9"/> <lire:column-info name="sessions_count" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="2"/> <lire:column-info name="sessions_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="5" missing-cases="0"> <lire:value col="sessions_count" missing-cases="0">5</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="5">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="rangegroup:session_length" value="0" range="60">[0s-1m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="rangegroup:session_length" value="60" range="60">[1m-2m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="rangegroup:session_length" value="120" range="60">[2m-3m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="rangegroup:session_length" value="180" range="60">[3m-4m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="rangegroup:session_length" value="240" range="60">[4m-5m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="5"> <lire:name col="rangegroup:session_length" value="300" range="60">[5m-6m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="6"> <lire:name col="rangegroup:session_length" value="360" range="60">[6m-7m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="7"> <lire:name col="rangegroup:session_length" value="420" range="60">[7m-8m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="8"> <lire:name col="rangegroup:session_length" value="480" range="60">[8m-9m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="9"> <lire:name col="rangegroup:session_length" value="540" range="60">[9m-10m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="10"> <lire:name col="rangegroup:session_length" value="600" range="60">[10m-11m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="11"> <lire:name col="rangegroup:session_length" value="660" range="60">[11m-12m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="12"> <lire:name col="rangegroup:session_length" value="720" range="60">[12m-13m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="13"> <lire:name col="rangegroup:session_length" value="780" range="60">[13m-14m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="14"> <lire:name col="rangegroup:session_length" value="840" range="60">[14m-15m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="15"> <lire:name col="rangegroup:session_length" value="900" range="60">[15m-16m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="16"> <lire:name col="rangegroup:session_length" value="960" range="60">[16m-17m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="17"> <lire:name col="rangegroup:session_length" value="1020" range="60">[17m-18m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="18"> <lire:name col="rangegroup:session_length" value="1080" range="60">[18m-19m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="19"> <lire:name col="rangegroup:session_length" value="1140" range="60">[19m-20m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="20"> <lire:name col="rangegroup:session_length" value="1200" range="60">[20m-21m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="21"> <lire:name col="rangegroup:session_length" value="1260" range="60">[21m-22m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="22"> <lire:name col="rangegroup:session_length" value="1320" range="60">[22m-23m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="23"> <lire:name col="rangegroup:session_length" value="1380" range="60">[23m-24m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="24"> <lire:name col="rangegroup:session_length" value="1440" range="60">[24m-25m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="25"> <lire:name col="rangegroup:session_length" value="1500" range="60">[25m-26m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="26"> <lire:name col="rangegroup:session_length" value="1560" range="60">[26m-27m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="27"> <lire:name col="rangegroup:session_length" value="1620" range="60">[27m-28m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="28"> <lire:name col="rangegroup:session_length" value="1680" range="60">[28m-29m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="29"> <lire:name col="rangegroup:session_length" value="1740" range="60">[29m-30m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="30"> <lire:name col="rangegroup:session_length" value="1800" range="60">[30m-31m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="31"> <lire:name col="rangegroup:session_length" value="1860" range="60">[31m-32m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="32"> <lire:name col="rangegroup:session_length" value="1920" range="60">[32m-33m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="33"> <lire:name col="rangegroup:session_length" value="1980" range="60">[33m-34m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="34"> <lire:name col="rangegroup:session_length" value="2040" range="60">[34m-35m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="35"> <lire:name col="rangegroup:session_length" value="2100" range="60">[35m-36m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="36"> <lire:name col="rangegroup:session_length" value="2160" range="60">[36m-37m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="37"> <lire:name col="rangegroup:session_length" value="2220" range="60">[37m-38m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="38"> <lire:name col="rangegroup:session_length" value="2280" range="60">[38m-39m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="39"> <lire:name col="rangegroup:session_length" value="2340" range="60">[39m-40m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="40"> <lire:name col="rangegroup:session_length" value="2400" range="60">[40m-41m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="41"> <lire:name col="rangegroup:session_length" value="2460" range="60">[41m-42m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="42"> <lire:name col="rangegroup:session_length" value="2520" range="60">[42m-43m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="43"> <lire:name col="rangegroup:session_length" value="2580" range="60">[43m-44m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="44"> <lire:name col="rangegroup:session_length" value="2640" range="60">[44m-45m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="45"> <lire:name col="rangegroup:session_length" value="2700" range="60">[45m-46m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="sessions-by-user_class.0" type="sessions-by-user_class" superservice="test" schemas="test-derived"> <lire:title>Sessions by User Class</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user_class" class="categorical" type="string" col-start="0" col-end="0" col-width="10" label="user_class" max-chars="10" avg-chars="10"/> <lire:column-info name="sessions_total" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="5" missing-cases="5"> <lire:value col="sessions_total" missing-cases="0">5</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Download Reports</lire:title> <lire:subreport id="avg-file_size-by-timeslot.0" type="avg-file_size-by-timeslot" superservice="test" schemas="test"> <lire:title>Average File Size By 1h Timeslot</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timeslot:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="6" label="Length" max-chars="6" avg-chars="6"/> <lire:column-info name="avg_file_size" class="numerical" type="bytes" col-start="1" col-end="1" col-width="13" label="Avg File Size" max-chars="13" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="avg_file_size" missing-cases="0" total="9037995" n="24" value="376583.12">367.8k</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timeslot:time_start" value="2-0" range="1">00:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timeslot:time_start" value="2-1" range="1">01:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="timeslot:time_start" value="2-2" range="1">02:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="timeslot:time_start" value="2-3" range="1">03:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="timeslot:time_start" value="2-4" range="1">04:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="5"> <lire:name col="timeslot:time_start" value="2-5" range="1">05:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="6"> <lire:name col="timeslot:time_start" value="2-6" range="1">06:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="7"> <lire:name col="timeslot:time_start" value="2-7" range="1">07:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="8"> <lire:name col="timeslot:time_start" value="2-8" range="1">08:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="9"> <lire:name col="timeslot:time_start" value="2-9" range="1">09:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="10"> <lire:name col="timeslot:time_start" value="2-10" range="1">10:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="11"> <lire:name col="timeslot:time_start" value="2-11" range="1">11:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="12"> <lire:name col="timeslot:time_start" value="2-12" range="1">12:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="6713494" n="23" value="291891.04">285.0k</lire:value> </lire:entry> <lire:entry row-idx="13"> <lire:name col="timeslot:time_start" value="2-13" range="1">13:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="14"> <lire:name col="timeslot:time_start" value="2-14" range="1">14:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="15"> <lire:name col="timeslot:time_start" value="2-15" range="1">15:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="2324501" n="1" value="2324501.00">2.2M</lire:value> </lire:entry> <lire:entry row-idx="16"> <lire:name col="timeslot:time_start" value="2-16" range="1">16:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="17"> <lire:name col="timeslot:time_start" value="2-17" range="1">17:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="18"> <lire:name col="timeslot:time_start" value="2-18" range="1">18:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="19"> <lire:name col="timeslot:time_start" value="2-19" range="1">19:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="20"> <lire:name col="timeslot:time_start" value="2-20" range="1">20:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="21"> <lire:name col="timeslot:time_start" value="2-21" range="1">21:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="22"> <lire:name col="timeslot:time_start" value="2-22" range="1">22:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="23"> <lire:name col="timeslot:time_start" value="2-23" range="1">23:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="user_downloads-report.0" type="user_downloads-report" superservice="test" schemas="test"> <lire:title>User's Downloads Report</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user" class="categorical" type="string" col-start="0" col-end="3" col-width="2" label="Username" max-chars="8" avg-chars="7"/> <lire:column-info name="first_file" class="numerical" type="filename" col-start="4" col-end="4" col-width="20" label="First File" max-chars="20" avg-chars="18"/> <lire:column-info name="last_file" class="numerical" type="filename" col-start="5" col-end="5" col-width="20" label="Last File" max-chars="20" avg-chars="18"/> <lire:column-info name="min_file_size" class="numerical" type="bytes" col-start="6" col-end="6" col-width="8" label="Smallest" max-chars="8" avg-chars="6"/> <lire:column-info name="max_file_size" class="numerical" type="bytes" col-start="7" col-end="7" col-width="7" label="Largest" max-chars="7" avg-chars="5"/> <lire:group-info name="records:3" row-idx="1"> <lire:column-info name="time_start" class="categorical" type="timestamp" col-start="1" col-end="1" col-width="19" label="Start Time" max-chars="19" avg-chars="19"/> <lire:column-info name="file" class="categorical" type="filename" col-start="2" col-end="2" col-width="20" label="File" max-chars="20" avg-chars="19"/> <lire:column-info name="file_size" class="categorical" type="bytes" col-start="3" col-end="3" col-width="6" label="Size" max-chars="6" avg-chars="5"/> </lire:group-info> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="first_file" missing-cases="0" total="1043514000">/pictures/000001.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="13245">12.9k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="user">bjoy</lire:name> <lire:value col="first_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="1" missing-cases="0" row-idx="0"> </lire:group-summary> <lire:entry row-idx="1"> <lire:name col="time_start" value="1043526410">2003-01-25 15:26:50</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="2"> <lire:name col="user">flacoste</lire:name> <lire:value col="first_file" missing-cases="0" total="1043514300">/movies/000002.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043515075">/movies/000003.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="232450">227.0k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="1324500">1.3M</lire:value> <lire:group> <lire:group-summary nrecords="2" missing-cases="0" row-idx="2"> </lire:group-summary> <lire:entry row-idx="3"> <lire:name col="time_start" value="1043514300">2003-01-25 12:05:00</lire:name> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:name col="file_size" value="1324500">1.3M</lire:name> </lire:entry> <lire:entry row-idx="4"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:name col="file_size" value="232450">227.0k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="5"> <lire:name col="user">francis</lire:name> <lire:value col="first_file" missing-cases="0" total="1043514000">/pictures/000001.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043515075">/pictures/000019.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="13245">12.9k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="13" missing-cases="0" row-idx="5"> </lire:group-summary> <lire:entry row-idx="6"> <lire:name col="time_start" value="1043514000">2003-01-25 12:00:00</lire:name> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:name col="file_size" value="13245">12.9k</lire:name> </lire:entry> <lire:entry row-idx="7"> <lire:name col="time_start" value="1043514305">2003-01-25 12:05:05</lire:name> <lire:name col="file">/pictures/001001.jpg</lire:name> <lire:name col="file_size" value="16432">16.0k</lire:name> </lire:entry> <lire:entry row-idx="8"> <lire:name col="time_start" value="1043514400">2003-01-25 12:06:40</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="9"> <lire:name col="time_start" value="1043515000">2003-01-25 12:16:40</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="10"> <lire:name col="time_start" value="1043515006">2003-01-25 12:16:46</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="11"> <lire:name col="time_start" value="1043515010">2003-01-25 12:16:50</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="12"> <lire:name col="time_start" value="1043515015">2003-01-25 12:16:55</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="13"> <lire:name col="time_start" value="1043515020">2003-01-25 12:17:00</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="14"> <lire:name col="time_start" value="1043515027">2003-01-25 12:17:07</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="15"> <lire:name col="time_start" value="1043515038">2003-01-25 12:17:18</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="16"> <lire:name col="time_start" value="1043515050">2003-01-25 12:17:30</lire:name> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="17"> <lire:name col="time_start" value="1043515057">2003-01-25 12:17:37</lire:name> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:name col="file_size" value="56345">55.0k</lire:name> </lire:entry> <lire:entry row-idx="18"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/pictures/000019.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="19"> <lire:name col="user">joostvb</lire:name> <lire:value col="first_file" missing-cases="0" total="1043516010">/pictures/000012.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043516037">/pictures/000016.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:group> <lire:group-summary nrecords="5" missing-cases="0" row-idx="19"> </lire:group-summary> <lire:entry row-idx="20"> <lire:name col="time_start" value="1043516010">2003-01-25 12:33:30</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="21"> <lire:name col="time_start" value="1043516015">2003-01-25 12:33:35</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="22"> <lire:name col="time_start" value="1043516020">2003-01-25 12:33:40</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="23"> <lire:name col="time_start" value="1043516027">2003-01-25 12:33:47</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="24"> <lire:name col="time_start" value="1043516037">2003-01-25 12:33:57</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="25"> <lire:name col="user">wdankers</lire:name> <lire:value col="first_file" missing-cases="0" total="1043516400">/movies/001145.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043516705">/pictures/000011.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="3" missing-cases="0" row-idx="25"> </lire:group-summary> <lire:entry row-idx="26"> <lire:name col="time_start" value="1043516400">2003-01-25 12:40:00</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="27"> <lire:name col="time_start" value="1043516701">2003-01-25 12:45:01</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="28"> <lire:name col="time_start" value="1043516705">2003-01-25 12:45:05</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> </lire:table> </lire:subreport> </lire:section> </lire:report> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test_report_cfg.xml���������������������������������������������������0000644�0001750�0001750�00000005165�10460672601�016704� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.0//EN" "http://www.logreport.org/LRCSML/1.0/lrcsml.dtd"> <lrcsml:config-spec xmlns="http://www.logreport.org/LRCML/" xmlns:lrcsml="http://www.logreport.org/LRCSML/"> <lrcsml:report-config name="test_default"> <param name="test_default"> <param name="id" value="test_default"/> <param name="sections"> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="All Files" /> <param name="specs"> <param name="test:top-files"> <param name="id" value="top-files.0" /> <param name="files_to_show" value="5" /> </param> <param name="test:top-dirs"> <param name="id" value="top-dirs.0" /> <param name="dirs_to_show" value="5" /> </param> <param name="test:downloads-by-period"> <param name="id" value="downloads-by-period.0" /> <param name="period" value="15m" /> </param> </param> </param> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="JPEG Files" /> <param name="filters"> <param name="test:select-file"> <param name="id" value="select-file.0" /> <param name="file_match" value=".*.jpg$" /> </param> </param> <param name="specs"> <param name="test:top-files"> <param name="id" value="top-files.1" /> <param name="files_to_show" value="5" /> </param> <param name="test:top-dirs"> <param name="id" value="top-dirs.1" /> <param name="dirs_to_show" value="5" /> </param> </param> </param> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="Sessions" /> <param name="specs"> <param name="test:sessions-by-length"> <param name="id" value="sessions-by-length.0" /> </param> <param name="test:sessions-by-user_class"> <param name="id" value="sessions-by-user_class.0" /> </param> </param> </param> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="Download Reports" /> <param name="specs"> <param name="test:avg-file_size-by-timeslot"> <param name="id" value="avg-file_size-by-timeslot.0" /> </param> <param name="test:user_downloads-report"> <param name="id" value="user_downloads-report.0" /> </param> </param> </param> </param> </param> </lrcsml:report-config> </lrcsml:config-spec> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test.cfg��������������������������������������������������������������0000644�0001750�0001750�00000000536�10460672601�014426� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������=section All Files top-files files_to_show=5 top-dirs dirs_to_show=5 downloads-by-period period=15m =section JPEG Files |select-file file_match=".*\.jpg$" top-files files_to_show=5 top-dirs dirs_to_show=5 =section Sessions sessions-by-length sessions-by-user_class =section Download Reports avg-file_size-by-timeslot unit=1h user_downloads-report ������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test.dlf��������������������������������������������������������������0000644�0001750�0001750�00000005555�10460672601�014442� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������LIRE_NOTAVAIL LIRE_NOTAVAIL 1043514000 1043514300 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000001.jpg 13245 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043514300 1043514600 LIRE_NOTAVAIL AABBCCDE 192.168.250.1 flacoste /movies/000002.mpg 1324500 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043514305 1043514355 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/001001.jpg 16432 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043514400 1043515000 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /movies/001145.mpg 2324501 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515000 1043515005 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000010.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515006 1043515010 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000011.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515010 1043515013 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000012.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515015 1043515020 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000013.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515020 1043515025 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000014.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515027 1043515036 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000015.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515038 1043515041 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000016.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515050 1043515055 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000017.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515057 1043515070 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000018.jpg 56345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515075 1043515080 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000019.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043515075 1043515475 LIRE_NOTAVAIL AABBCCDF 192.168.250.1 flacoste /movies/000003.mpg 232450 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043516010 1043516013 LIRE_NOTAVAIL AABBCCDG 192.168.250.2 joostvb /pictures/000012.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043516015 1043516020 LIRE_NOTAVAIL AABBCCDG 192.168.250.2 joostvb /pictures/000013.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043516020 1043516025 LIRE_NOTAVAIL AABBCCDG 192.168.250.2 joostvb /pictures/000014.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043516027 1043516036 LIRE_NOTAVAIL AABBCCDG 192.168.250.2 joostvb /pictures/000015.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043516037 1043516041 LIRE_NOTAVAIL AABBCCDG 192.168.250.2 joostvb /pictures/000016.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043516400 1043516700 LIRE_NOTAVAIL AABBCCDD 192.168.250.3 wdankers /movies/001145.mpg 2324501 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043526410 1043526500 LIRE_NOTAVAIL AABBCCDH 192.168.250.4 bjoy /movies/001145.mpg 2324501 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043516701 1043516705 LIRE_NOTAVAIL AABBCCDD 192.168.250.3 wdankers /pictures/000010.jpg 26345 1 LIRE_NOTAVAIL LIRE_NOTAVAIL 1043516705 1043516715 LIRE_NOTAVAIL AABBCCDD 192.168.250.3 wdankers /pictures/000011.jpg 26345 1 ���������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-cfg_spec.xml�����������������������������������������������������0000644�0001750�0001750�00000002250�10460672600�016230� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.0//EN" "http://www.logreport.org/LRCSML/1.0/lrcsml.dtd"> <lrcsml:config-spec xmlns:lrcsml="http://www.logreport.org/LRCSML/"> <!-- $Id: test-cfg_spec.xml,v 1.2 2004/05/27 00:34:56 wsourdeau Exp $ --> <lrcsml:boolean name="var1" section="section1" contexts="global job"> <lrcsml:summary>Var1 summary</lrcsml:summary> <lrcsml:description> <para>Var1 description with many lines. </para></lrcsml:description> </lrcsml:boolean> <lrcsml:select name="select2" section="operation" contexts="global job"> <lrcsml:summary>Select2 summary</lrcsml:summary> <lrcsml:description> <para>Select2 description</para> </lrcsml:description> <lrcsml:option name="option1"> <lrcsml:summary>Explanation on option1</lrcsml:summary> </lrcsml:option> <lrcsml:option name="option2"> <lrcsml:summary>option2 summary</lrcsml:summary> <lrcsml:description> <para>option2 description</para> </lrcsml:description> </lrcsml:option> </lrcsml:select> </lrcsml:config-spec> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-regular.msg������������������������������������������������������0000644�0001750�0001750�00000006077�10460672601�016122� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������From flacoste@logreport.org Wed Apr 30 11:46:45 2003 Return-Path: <flacoste@logreport.org> Delivered-To: log@test.logreport.org Subject: Test DLF file (uncrompressed) From: "Francis J. Lacoste" <flacoste@logreport.org> To: log@test.logreport.org Content-Type: multipart/mixed; boundary="=-j1GER6+G5wilPuzxSCuQ" X-Mailer: Ximian Evolution 1.0.5 Date: 30 Apr 2003 11:46:44 -0400 Message-Id: <1051717604.8532.66.camel@Arendt.Contre.COM> Mime-Version: 1.0 --=-j1GER6+G5wilPuzxSCuQ Content-Type: text/plain Content-Transfer-Encoding: 8bit -- Francis J. Lacoste . . http://www.logreport.org /^LogReport$/ . . flacoste@logreport.org --=-j1GER6+G5wilPuzxSCuQ Content-Disposition: attachment; filename=test.dlf Content-Type: text/plain; name=test.dlf; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit 1043514000 1043514300 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000001.jpg 13245 1 1043514300 1043514600 LIRE_NOTAVAIL AABBCCDE 192.168.250.1 flacoste /movies/000002.mpg 1324500 1 1043514305 1043514355 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/001001.jpg 16432 1 1043514400 1043515000 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /movies/001145.mpg 2324501 1 1043515000 1043515005 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000010.jpg 26345 1 1043515006 1043515010 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000011.jpg 26345 1 1043515010 1043515013 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000012.jpg 26345 1 1043515015 1043515020 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000013.jpg 26345 1 1043515020 1043515025 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000014.jpg 26345 1 1043515027 1043515036 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000015.jpg 26345 1 1043515038 1043515041 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000016.jpg 26345 1 1043515050 1043515055 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000017.jpg 26345 1 1043515057 1043515070 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000018.jpg 56345 1 1043515075 1043515080 LIRE_NOTAVAIL AABBCCDD 127.0.0.1 francis /pictures/000019.jpg 26345 1 1043515075 1043515475 LIRE_NOTAVAIL AABBCCDF 192.168.250.1 flacoste /movies/000003.mpg 232450 1 1043516010 1043516013 LIRE_NOTAVAIL AABBCCDG 192.168.250.2 joostvb /pictures/000012.jpg 26345 1 1043516015 1043516020 LIRE_NOTAVAIL AABBCCDG 192.168.250.2 joostvb /pictures/000013.jpg 26345 1 1043516020 1043516025 LIRE_NOTAVAIL AABBCCDG 192.168.250.2 joostvb /pictures/000014.jpg 26345 1 1043516027 1043516036 LIRE_NOTAVAIL AABBCCDG 192.168.250.2 joostvb /pictures/000015.jpg 26345 1 1043516037 1043516041 LIRE_NOTAVAIL AABBCCDG 192.168.250.2 joostvb /pictures/000016.jpg 26345 1 1043516400 1043516700 LIRE_NOTAVAIL AABBCCDD 192.168.250.3 wdankers /movies/001145.mpg 2324501 1 1043526410 1043526500 LIRE_NOTAVAIL AABBCCDH 192.168.250.4 bjoy /movies/001145.mpg 2324501 1 1043516701 1043516705 LIRE_NOTAVAIL AABBCCDD 192.168.250.3 wdankers /pictures/000010.jpg 26345 1 1043516705 1043516715 LIRE_NOTAVAIL AABBCCDD 192.168.250.3 wdankers /pictures/000011.jpg 26345 1 --=-j1GER6+G5wilPuzxSCuQ-- �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-l10n_cfg.xml�����������������������������������������������������0000644�0001750�0001750�00000002421�10460672600�016050� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.0//EN" "http://www.logreport.org/LRCSML/1.0/lrcsml.dtd"> <lrcsml:config-spec xmlns="http://www.logreport.org/LRCML/" xmlns:lrcsml="http://www.logreport.org/LRCSML/"> <lrcsml:report-config name="test-l10n"> <param name="test-l10n"> <param name="id">test_l10n</param> <param name="sections"> <param name="section"> <param name="specs"> <param name="test:top-files"> <param name="files_to_show">5</param> <param name="id">top-files.0</param> </param> <param name="test:top-dirs"> <param name="dirs_to_show">5</param> <param name="id">top-dirs.0</param> </param> </param> <param name="filters"> <param name="test:select-file"> <param name="file_match">.*.jpg$</param> <param name="id">select-file.0</param> </param> </param> <param name="title">JPEG Files</param> <param name="superservice">test</param> </param> </param> </param> </lrcsml:report-config> </lrcsml:config-spec> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-utf8_cfg.xml�����������������������������������������������������0000644�0001750�0001750�00000001650�10460672601�016170� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <!DOCTYPE lrcsml:config-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Specification Markup Language V1.0//EN" "http://www.logreport.org/LRCSML/1.0/lrcsml.dtd"> <lrcsml:config-spec xmlns="http://www.logreport.org/LRCML/" xmlns:lrcsml="http://www.logreport.org/LRCSML/"> <lrcsml:report-config name="test_utf8"> <param name="test_utf8"> <param name="id">test_utf8</param> <param name="sections"> <param name="section"> <param name="specs"> <param name="test:user-downloads-utf8"> <param name="users_to_show">5</param> <param name="id">user-downloads-utf8.0</param> </param> </param> <param name="title">Téléchargements</param> <param name="superservice">test</param> </param> </param> </param> </lrcsml:report-config> </lrcsml:config-spec> ����������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test.pot.pl�����������������������������������������������������������0000644�0001750�0001750�00000006125�10460672601�015103� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# REFERENCE: test_report_cfg.xml __( q{All Files} ); # REFERENCE: test_report_cfg.xml __( q{JPEG Files} ); # REFERENCE: test_report_cfg.xml __( q{Sessions} ); # REFERENCE: test_report_cfg.xml __( q{Download Reports} ); # REFERENCE: schema:test __( q{Simple Schema Definition for Test} ); # REFERENCE: schema:test __( q{Simple schema definition for testing purpose} ); # REFERENCE: schema:test __( q{Start Time} ); # REFERENCE: schema:test __( q{Start time of the file transfer.} ); # REFERENCE: schema:test __( q{End Time} ); # REFERENCE: schema:test __( q{The time at which the transfer ended.} ); # REFERENCE: schema:test __( q{Duration} ); # REFERENCE: schema:test __( q{Time taken by the transfer.} ); # REFERENCE: schema:test __( q{Connection ID} ); # REFERENCE: schema:test __( q{Connection identifier. } ); # REFERENCE: schema:test __( q{Client Host} ); # REFERENCE: schema:test __( q{The host to which the file was transferred.} ); # REFERENCE: schema:test __( q{Username} ); # REFERENCE: schema:test __( q{Name of the authenticated user that did the file transfer. } ); # REFERENCE: schema:test __( q{File} ); # REFERENCE: schema:test __( q{The file that was transferred. } ); # REFERENCE: schema:test __( q{Size} ); # REFERENCE: schema:test __( q{The number of bytes transferred.} ); # REFERENCE: schema:test __( q{Complete?} ); # REFERENCE: schema:test __( q{Was the file transferred completely?} ); # REFERENCE: schema:test-extended __( q{Simple Extended Schema for Tests} ); # REFERENCE: schema:test-extended __( q{Simple extended schema for testing purpose.} ); # REFERENCE: schema:test-extended __( q{Directory} ); # REFERENCE: schema:test-extended __( q{Contains the file's directory.} ); # REFERENCE: report:test:top-dirs __( q{Top Directories Report Specification} ); # REFERENCE: report:test:top-dirs __( q{Test report specification using an extended schema.} ); # REFERENCE: report:test:top-dirs __( q{Downloads by Directory, Top $dirs_to_show} ); # REFERENCE: report:test:top-dirs __( q{Bytes Downloaded} ); # REFERENCE: report:test:top-dirs __( q{% Total} ); # REFERENCE: report:test:top-files __( q{Top Files Report Specification} ); # REFERENCE: report:test:top-files __( q{Test report specification.} ); # REFERENCE: report:test:top-files __( q{Downloads by File, Top $files_to_show} ); # REFERENCE: report:test:top-files __( q{Downloads} ); # REFERENCE: report:test:top-files __( q{% Total} ); # REFERENCE: filter:test:select-file __( q{Select File Filter Specification} ); # REFERENCE: filter:test:select-file __( q{Test global filter specification. } ); # REFERENCE: filter:test:select-file __( q{Test parameter.} ); # REFERENCE: filter:test:select-file __( q{selected files matching $file_match} ); # REFERENCE: test-cfg_spec.xml __( q{Select2 summary} ); # REFERENCE: test-cfg_spec.xml __( q{Select2 description} ); # REFERENCE: test-cfg_spec.xml __( q{Explanation on option1} ); # REFERENCE: test-cfg_spec.xml __( q{option2 summary} ); # REFERENCE: test-cfg_spec.xml __( q{option2 description} ); # REFERENCE: test-cfg_spec.xml __( q{Var1 summary} ); # REFERENCE: test-cfg_spec.xml __( q{Var1 description with many lines.} ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/TestReport_daily_jan25_2003.xml���������������������������������������0000644�0001750�0001750�00000074450�10460672600�020455� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "http://www.logreport.org/LRML/2.1/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" xmlns:lrcml="http://www.logreport.org/LRCML/" version="2.1"> <!-- generated by Lire::Report(3pm) --> <lire:date time="1081356400">2004-04-07 11:46:40 EST</lire:date> <lire:timespan start="1043514000" end="1043526410">2003-01-25 12:00:00 EST - 2003-01-25 15:26:50 EST</lire:timespan> <lire:section> <lire:title>All Files</lire:title> <lire:subreport id="top-files.0" type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="File" max-chars="20" avg-chars="17"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="request_total" missing-cases="0">24</lire:value> <lire:value col="request_ratio" missing-cases="0" value="24">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:value col="request_total" missing-cases="0">3</lire:value> <lire:value col="request_ratio" missing-cases="0" value="3">12.5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">4.2</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">4.2</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="top-dirs.0" type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="8"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0" value="9037995">8.6M</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="9037995">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/movies</lire:name> <lire:value col="bytes_total" missing-cases="0" value="8530453">8.1M</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="8530453">94.4</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" missing-cases="0" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">5.6</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="downloads-by-period.0" type="downloads-by-period" superservice="test" schemas="test"> <lire:title>Download by 15m Period</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timegroup:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="16" label="Period" max-chars="16" avg-chars="15"/> <lire:column-info name="download_count" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="download_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> <lire:column-info name="user_count" class="numerical" type="int" col-start="3" col-end="3" col-width="12" label="Unique Users" max-chars="12" avg-chars="3"/> <lire:column-info name="user_ratio" class="numerical" type="int" col-start="4" col-end="4" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="download_count" missing-cases="0">24</lire:value> <lire:value col="download_ratio" missing-cases="0" value="24">100.0</lire:value> <lire:value col="user_count" missing-cases="0">5</lire:value> <lire:value col="user_ratio" missing-cases="0" value="5">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timegroup:time_start" value="1043514000" range="900">2003-01-25 12:00</lire:name> <lire:value col="download_count" missing-cases="0">4</lire:value> <lire:value col="download_ratio" missing-cases="0" value="4">16.7</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timegroup:time_start" value="1043514900" range="900"> 12:15</lire:name> <lire:value col="download_count" missing-cases="0">11</lire:value> <lire:value col="download_ratio" missing-cases="0" value="11">45.8</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="timegroup:time_start" value="1043515800" range="900"> 12:30</lire:name> <lire:value col="download_count" missing-cases="0">6</lire:value> <lire:value col="download_ratio" missing-cases="0" value="6">25.0</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="timegroup:time_start" value="1043516700" range="900"> 12:45</lire:name> <lire:value col="download_count" missing-cases="0">2</lire:value> <lire:value col="download_ratio" missing-cases="0" value="2">8.3</lire:value> <lire:value col="user_count" missing-cases="0">1</lire:value> <lire:value col="user_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="timegroup:time_start" value="1043525700" range="900"> 15:15</lire:name> <lire:value col="download_count" missing-cases="0">1</lire:value> <lire:value col="download_ratio" missing-cases="0" value="1">4.2</lire:value> <lire:value col="user_count" missing-cases="0">1</lire:value> <lire:value col="user_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> </lire:table> <lire:chart-configs> <lrcml:param name="chart"> <lrcml:param name="title" value="Users and Downloads by 15m" /> <lrcml:param name="case_var" value="timegroup:time_start" /> <lrcml:param name="type" value="vbars"> <lrcml:param name="y" value="download_count" /> <lrcml:param name="y2" value="user_count" /> </lrcml:param> </lrcml:param> </lire:chart-configs> </lire:subreport> </lire:section> <lire:section> <lire:title>JPEG Files</lire:title> <lire:description><para>Applied filter in this section: selected files matching .*.jpg$</para> </lire:description> <lire:subreport id="top-files.1" type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="File" max-chars="20" avg-chars="18"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="19" missing-cases="0"> <lire:value col="request_total" missing-cases="0">19</lire:value> <lire:value col="request_ratio" missing-cases="0" value="19">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5.3</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="top-dirs.1" type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="10"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="6"/> </lire:table-info> <lire:group-summary nrecords="19" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" missing-cases="0" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">100.0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Sessions</lire:title> <lire:subreport id="sessions-by-length.0" type="sessions-by-length" superservice="test" schemas="test-derived"> <lire:title>Sessions by Length</lire:title> <lire:table> <lire:table-info> <lire:column-info name="rangegroup:session_length" class="categorical" type="duration" col-start="0" col-end="0" col-width="9" label="Length" max-chars="9" avg-chars="8"/> <lire:column-info name="sessions_count" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="2"/> <lire:column-info name="sessions_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="5" missing-cases="0"> <lire:value col="sessions_count" missing-cases="0">5</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="5">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="rangegroup:session_length" value="0" range="60">[0s-1m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="rangegroup:session_length" value="60" range="60">[1m-2m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="rangegroup:session_length" value="300" range="60">[5m-6m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="rangegroup:session_length" value="360" range="60">[6m-7m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="rangegroup:session_length" value="2700" range="60">[45m-46m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="sessions-by-user_class.0" type="sessions-by-user_class" superservice="test" schemas="test-derived"> <lire:title>Sessions by User Class</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user_class" class="categorical" type="string" col-start="0" col-end="0" col-width="10" label="user_class" max-chars="10" avg-chars="10"/> <lire:column-info name="sessions_total" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="5" missing-cases="5"> <lire:value col="sessions_total" missing-cases="0">5</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Download Reports</lire:title> <lire:subreport id="avg-file_size-by-timeslot.0" type="avg-file_size-by-timeslot" superservice="test" schemas="test"> <lire:title>Average File Size By 1h Timeslot</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timeslot:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="6" label="Length" max-chars="6" avg-chars="6"/> <lire:column-info name="avg_file_size" class="numerical" type="bytes" col-start="1" col-end="1" col-width="13" label="Avg File Size" max-chars="13" avg-chars="8"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="avg_file_size" missing-cases="0" total="9037995" n="24" value="376583.12">367.8k</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timeslot:time_start" value="2-12" range="1">12:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="6713494" n="23" value="291891.04">285.0k</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timeslot:time_start" value="2-15" range="1">15:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="2324501" n="1" value="2324501.00">2.2M</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport id="user_downloads-report.0" type="user_downloads-report" superservice="test" schemas="test"> <lire:title>User's Downloads Report</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user" class="categorical" type="string" col-start="0" col-end="3" col-width="2" label="Username" max-chars="8" avg-chars="7"/> <lire:column-info name="first_file" class="numerical" type="filename" col-start="4" col-end="4" col-width="20" label="First File" max-chars="20" avg-chars="18"/> <lire:column-info name="last_file" class="numerical" type="filename" col-start="5" col-end="5" col-width="20" label="Last File" max-chars="20" avg-chars="18"/> <lire:column-info name="min_file_size" class="numerical" type="bytes" col-start="6" col-end="6" col-width="8" label="Smallest" max-chars="8" avg-chars="6"/> <lire:column-info name="max_file_size" class="numerical" type="bytes" col-start="7" col-end="7" col-width="7" label="Largest" max-chars="7" avg-chars="5"/> <lire:group-info name="records:3" row-idx="1"> <lire:column-info name="time_start" class="categorical" type="timestamp" col-start="1" col-end="1" col-width="19" label="Start Time" max-chars="19" avg-chars="19"/> <lire:column-info name="file" class="categorical" type="filename" col-start="2" col-end="2" col-width="20" label="File" max-chars="20" avg-chars="19"/> <lire:column-info name="file_size" class="categorical" type="bytes" col-start="3" col-end="3" col-width="6" label="Size" max-chars="6" avg-chars="5"/> </lire:group-info> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="first_file" missing-cases="0" total="1043514000">/pictures/000001.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="13245">12.9k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="user">bjoy</lire:name> <lire:value col="first_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="1" missing-cases="0" row-idx="0"> </lire:group-summary> <lire:entry row-idx="1"> <lire:name col="time_start" value="1043526410">2003-01-25 15:26:50</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="2"> <lire:name col="user">flacoste</lire:name> <lire:value col="first_file" missing-cases="0" total="1043514300">/movies/000002.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043515075">/movies/000003.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="232450">227.0k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="1324500">1.3M</lire:value> <lire:group> <lire:group-summary nrecords="2" missing-cases="0" row-idx="2"> </lire:group-summary> <lire:entry row-idx="3"> <lire:name col="time_start" value="1043514300">2003-01-25 12:05:00</lire:name> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:name col="file_size" value="1324500">1.3M</lire:name> </lire:entry> <lire:entry row-idx="4"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:name col="file_size" value="232450">227.0k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="5"> <lire:name col="user">francis</lire:name> <lire:value col="first_file" missing-cases="0" total="1043514000">/pictures/000001.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043515075">/pictures/000019.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="13245">12.9k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="13" missing-cases="0" row-idx="5"> </lire:group-summary> <lire:entry row-idx="6"> <lire:name col="time_start" value="1043514000">2003-01-25 12:00:00</lire:name> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:name col="file_size" value="13245">12.9k</lire:name> </lire:entry> <lire:entry row-idx="7"> <lire:name col="time_start" value="1043514305">2003-01-25 12:05:05</lire:name> <lire:name col="file">/pictures/001001.jpg</lire:name> <lire:name col="file_size" value="16432">16.0k</lire:name> </lire:entry> <lire:entry row-idx="8"> <lire:name col="time_start" value="1043514400">2003-01-25 12:06:40</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="9"> <lire:name col="time_start" value="1043515000">2003-01-25 12:16:40</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="10"> <lire:name col="time_start" value="1043515006">2003-01-25 12:16:46</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="11"> <lire:name col="time_start" value="1043515010">2003-01-25 12:16:50</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="12"> <lire:name col="time_start" value="1043515015">2003-01-25 12:16:55</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="13"> <lire:name col="time_start" value="1043515020">2003-01-25 12:17:00</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="14"> <lire:name col="time_start" value="1043515027">2003-01-25 12:17:07</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="15"> <lire:name col="time_start" value="1043515038">2003-01-25 12:17:18</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="16"> <lire:name col="time_start" value="1043515050">2003-01-25 12:17:30</lire:name> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="17"> <lire:name col="time_start" value="1043515057">2003-01-25 12:17:37</lire:name> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:name col="file_size" value="56345">55.0k</lire:name> </lire:entry> <lire:entry row-idx="18"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/pictures/000019.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="19"> <lire:name col="user">joostvb</lire:name> <lire:value col="first_file" missing-cases="0" total="1043516010">/pictures/000012.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043516037">/pictures/000016.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:group> <lire:group-summary nrecords="5" missing-cases="0" row-idx="19"> </lire:group-summary> <lire:entry row-idx="20"> <lire:name col="time_start" value="1043516010">2003-01-25 12:33:30</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="21"> <lire:name col="time_start" value="1043516015">2003-01-25 12:33:35</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="22"> <lire:name col="time_start" value="1043516020">2003-01-25 12:33:40</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="23"> <lire:name col="time_start" value="1043516027">2003-01-25 12:33:47</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="24"> <lire:name col="time_start" value="1043516037">2003-01-25 12:33:57</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="25"> <lire:name col="user">wdankers</lire:name> <lire:value col="first_file" missing-cases="0" total="1043516400">/movies/001145.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043516705">/pictures/000011.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="3" missing-cases="0" row-idx="25"> </lire:group-summary> <lire:entry row-idx="26"> <lire:name col="time_start" value="1043516400">2003-01-25 12:40:00</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="27"> <lire:name col="time_start" value="1043516701">2003-01-25 12:45:01</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="28"> <lire:name col="time_start" value="1043516705">2003-01-25 12:45:05</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> </lire:table> </lire:subreport> </lire:section> </lire:report> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-empty-sqlite.xml�������������������������������������������������0000644�0001750�0001750�00000025025�10460672600�017121� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "http://www.logreport.org/LRML/2.1/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" xmlns:lrcml="http://www.logreport.org/LRCML/" version="2.1"> <!-- generated by Lire::Report(3pm) --> <lire:date time="1093832162">2004-08-29 21:16:02 EST</lire:date> <lire:timespan start="" end="">Unknown Period</lire:timespan> <lire:section> <lire:title>All Files</lire:title> <lire:subreport id="top-files.0" superservice="test" type="top-files" schemas='test'> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="4" label="File" max-chars="4" avg-chars="4"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="5"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="request_total" missing-cases="0">0</lire:value> <lire:value col="request_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> <lire:subreport id="top-dirs.0" superservice="test" type="top-dirs" schemas='test-extended'> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="9"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0">0</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> <lire:subreport id="downloads-by-period.0" superservice="test" type="downloads-by-period" schemas='test'> <lire:title>Download by 15m Period</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timegroup:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="6" label="Period" max-chars="6" avg-chars="6"/> <lire:column-info name="download_count" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="5"/> <lire:column-info name="download_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> <lire:column-info name="user_count" class="numerical" type="int" col-start="3" col-end="3" col-width="12" label="Unique Users" max-chars="12" avg-chars="8"/> <lire:column-info name="user_ratio" class="numerical" type="int" col-start="4" col-end="4" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">NaN</lire:value> <lire:value col="user_count" missing-cases="0">NaN</lire:value> <lire:value col="user_ratio" missing-cases="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>JPEG Files</lire:title> <lire:description><para>Applied filter in this section: selected files matching .*.jpg$</para> </lire:description> <lire:subreport id="top-files.1" superservice="test" type="top-files" schemas='test'> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="4" label="File" max-chars="4" avg-chars="4"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="5"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="request_total" missing-cases="0">0</lire:value> <lire:value col="request_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> <lire:subreport id="top-dirs.1" superservice="test" type="top-dirs" schemas='test-extended'> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="9"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0">0</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Sessions</lire:title> <lire:subreport id="sessions-by-length.0" superservice="test" type="sessions-by-length" schemas='test-derived'> <lire:title>Sessions by Length</lire:title> <lire:table> <lire:table-info> <lire:column-info name="rangegroup:session_length" class="categorical" type="duration" col-start="0" col-end="0" col-width="6" label="Length" max-chars="6" avg-chars="6"/> <lire:column-info name="sessions_count" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="5"/> <lire:column-info name="sessions_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> <lire:subreport id="sessions-by-user_class.0" superservice="test" type="sessions-by-user_class" schemas='test-derived'> <lire:title>Sessions by User Class</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user_class" class="categorical" type="string" col-start="0" col-end="0" col-width="10" label="user_class" max-chars="10" avg-chars="10"/> <lire:column-info name="sessions_total" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="sessions_total" missing-cases="0">0</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Download Reports</lire:title> <lire:subreport id="avg-file_size-by-timeslot.0" superservice="test" type="avg-file_size-by-timeslot" schemas='test'> <lire:title>Average File Size By 1h Timeslot</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timeslot:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="6" label="Length" max-chars="6" avg-chars="6"/> <lire:column-info name="avg_file_size" class="numerical" type="bytes" col-start="1" col-end="1" col-width="13" label="Avg File Size" max-chars="13" avg-chars="8"/> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> <lire:subreport id="user_downloads-report.0" superservice="test" type="user_downloads-report" schemas='test'> <lire:title>User's Downloads Report</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user" class="categorical" type="string" col-start="0" col-end="3" col-width="2" label="Username" max-chars="8" avg-chars="8"/> <lire:column-info name="first_file" class="numerical" type="filename" col-start="4" col-end="4" col-width="10" label="First File" max-chars="10" avg-chars="5"/> <lire:column-info name="last_file" class="numerical" type="filename" col-start="5" col-end="5" col-width="9" label="Last File" max-chars="9" avg-chars="5"/> <lire:column-info name="min_file_size" class="numerical" type="bytes" col-start="6" col-end="6" col-width="8" label="Smallest" max-chars="8" avg-chars="6"/> <lire:column-info name="max_file_size" class="numerical" type="bytes" col-start="7" col-end="7" col-width="7" label="Largest" max-chars="7" avg-chars="5"/> <lire:group-info name="records:3" row-idx="1"> <lire:column-info name="time_start" class="categorical" type="timestamp" col-start="1" col-end="1" col-width="10" label="Start Time" max-chars="10" avg-chars="10"/> <lire:column-info name="file" class="categorical" type="filename" col-start="2" col-end="2" col-width="4" label="File" max-chars="4" avg-chars="4"/> <lire:column-info name="file_size" class="categorical" type="bytes" col-start="3" col-end="3" col-width="4" label="Size" max-chars="4" avg-chars="4"/> </lire:group-info> </lire:table-info> <lire:group-summary nrecords="0" missing-cases="0"> <lire:value col="first_file" missing-cases="0"></lire:value> <lire:value col="last_file" missing-cases="0"></lire:value> <lire:value col="min_file_size" missing-cases="0">NaN</lire:value> <lire:value col="max_file_size" missing-cases="0">NaN</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> </lire:report> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-compressed-anon.msg����������������������������������������������0000644�0001750�0001750�00000002727�10460672600�017553� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������From flacoste@logreport.org Wed Apr 30 11:46:45 2003 Return-Path: <flacoste@logreport.org> Delivered-To: log@test.logreport.org Subject: anon Test log file (compressed) From: "Francis J. Lacoste" <flacoste@logreport.org> To: log@test.logreport.org Reply-To: flacoste+anon@logreport.org Content-Type: multipart/mixed; boundary="=-7prf0mcjrnMJKcKFOvKs" X-Mailer: Ximian Evolution 1.0.5 Date: 30 Apr 2003 11:45:59 -0400 Message-Id: <1051717559.11991.64.camel@Arendt.Contre.COM> Mime-Version: 1.0 --=-7prf0mcjrnMJKcKFOvKs Content-Type: text/plain Content-Transfer-Encoding: 8bit -- Francis J. Lacoste . . http://www.logreport.org /^LogReport$/ . . flacoste@logreport.org --=-7prf0mcjrnMJKcKFOvKs Content-Disposition: attachment; filename=test.dlf.gz Content-Type: application/x-gzip; name=test.dlf.gz Content-Transfer-Encoding: base64 H4sICICMMkEAA3Rlc3QuZGxmAKXWz04CMRAG8LtP0SdYOtPO7Hpc/qgkG02M8WoA0YDCEkCMb2/Z ZFv2UG27cBkSwi9ft/mYavo4ebl/eCqfy2klqs4nkFoRaCllOyozdr9TlsPhaDQeC8A8k+YN4m0/ 2y5WBzHYrRbHr/3yMJDnF2Tr3bsAhZoEXFX/u8q57HMnAq4xAy4ypMb+nC3qw3EpBpv6tGppzDYt ff7NMJzsSJQWGmxo1grDXG1Dk4w6bJsXQFOTF5u8EOSSvHQT854TN3mRVeBDNhjbEZIvF0C0Cy4v qGQX412yI6bnVdEuuryY/nx1vJvbUXGyS9GuKuyoIdnlaJfcOaf2hnHzeNedc55+r4rGpQg3d/e5 SHevo/M6V+eec74J+nNQF2UZZLPrDvZ2x23HRrGujXya9+0Pdv3B3v4ItGM7hF2HsLdDAu3YHmHX I+ztkUA7tksM6GxflwTasX3Cbh/g/I994MJW4vt1tv1Y7vsuBci6vejI5MPvOrgW83X903cbMVHB jf4W9aTut5I0YjtCT7y7l/wCsRX1g20LAAA= --=-7prf0mcjrnMJKcKFOvKs-- �����������������������������������������lire-2.1.1/all/lib/tests/data/test_store.tar��������������������������������������������������������0000644�0001750�0001750�00000024000�11110776476�015671� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������test_store/�����������������������������������������������������������������������������������������0000750�0000764�0000764�00000000000�11035214761�012402� 5����������������������������������������������������������������������������������������������������ustar �wytze���������������������������wytze������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������test_store/dlf.db�����������������������������������������������������������������������������������0000644�0000764�0000764�00000012000�11035214623�013451� 0����������������������������������������������������������������������������������������������������ustar �wytze���������������������������wytze������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SQLite format 3���@ ������������������������������������������������������������������������ ���"�"��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������k; indexdlf_test_time_start_idxdlf_testCREATE INDEX dlf_test_time_start_idx ON dlf_test ( time_start )n/tabledlf_testdlf_testCREATE TABLE dlf_test ( dlf_id INTEGER PRIMARY KEY, dlf_source VARCHAR(512), time_start TIMESTAMP, time_end TIMESTAMP, time_taken NUMBER(10,1), connection_id VARCHAR(512), client_host VARCHAR(512), user VARCHAR(512), file VARCHAR(512), file_size NUMBER(10,1), "transfer-complete" NUMBER(1,0) )������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ����6�r-_K��{�6������������������C ���5>2>2AABBCCDD127.0.0.1francis/pictures/000019.jpgfD ���5>2Ʊ>2ƾAABBCCDD127.0.0.1francis/pictures/000018.jpg�C ���5>2ƪ>2ƯAABBCCDD127.0.0.1francis/pictures/000017.jpgfC ���5>2ƞ>2ơAABBCCDD127.0.0.1francis/pictures/000016.jpgfC ���5>2Ɠ>2ƜAABBCCDD127.0.0.1francis/pictures/000015.jpgfC ���5>2ƌ>2ƑAABBCCDD127.0.0.1francis/pictures/000014.jpgfC ���5>2Ƈ>2ƌAABBCCDD127.0.0.1francis/pictures/000013.jpgfC ���5>2Ƃ>2ƅAABBCCDD127.0.0.1francis/pictures/000012.jpgfC ���5>2~>2ƂAABBCCDD127.0.0.1francis/pictures/000011.jpgfC ���5>2x>2}AABBCCDD127.0.0.1francis/pictures/000010.jpgfB ���1>2 >2xAABBCCDD127.0.0.1francis/movies/001145.mpg#xC ���5>2>2AABBCCDD127.0.0.1francis/pictures/001001.jpg@0G ���'1>2ü>2AABBCCDE192.168.250.1flacoste/movies/000002.mpg5C ���5>2>2üAABBCCDD127.0.0.1francis/pictures/000001.jpg3 ��� (�n%Jr(����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H ���'5>2!>2+AABBCCDD192.168.250.3wdankers/pictures/000011.jpgfH ���'5>2>2!AABBCCDD192.168.250.3wdankers/pictures/000010.jpgfC ���'1>2 >2dAABBCCDH192.168.250.4bjoy/movies/001145.mpg#xG ���'1>2>2AABBCCDD192.168.250.3wdankers/movies/001145.mpg#xG ���'5>2ʅ>2ʉAABBCCDG192.168.250.2joostvb/pictures/000016.jpgfG ���'5>2{>2ʄAABBCCDG192.168.250.2joostvb/pictures/000015.jpgfG ���'5>2t>2yAABBCCDG192.168.250.2joostvb/pictures/000014.jpgfG ���'5>2o>2tAABBCCDG192.168.250.2joostvb/pictures/000013.jpgfG ���'5>2j>2mAABBCCDG192.168.250.2joostvb/pictures/000012.jpgfG ���'1>2>2SAABBCCDF192.168.250.1flacoste/movies/000003.mpg ���(�ypg^ULC1(:��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������>2!>2>2 >2>2ʅ>2{>2t>2o>2j>2>2>2Ʊ >2ƪ >2ƞ >2Ɠ >2ƌ >2Ƈ>2Ƃ>2~>2x>2 >2>2ü>2test_store/config.xml�������������������������������������������������������������������������������0000644�0000764�0000764�00000000453�10041772203�014374� 0����������������������������������������������������������������������������������������������������ustar �wytze���������������������������wytze������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE config PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Markup Language V1.0//EN" "http://www.logreport.org/LRCML/1.0/lrcml.dtd"[ <!ENTITY % LIRE.pfx ""> ]> <config xmlns="http://www.logreport.org/LRCML/"> <global> </global> </config> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-sqlite.xml�������������������������������������������������������0000644�0001750�0001750�00000073247�10460672601�015777� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="us-ascii"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "http://www.logreport.org/LRML/2.1/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" version="2.1"> <!-- generated by Lire::ReportParser::ReportBuilder(3pm) --> <lire:date time="1043632474">2003-01-26 20:54:34 EST</lire:date> <lire:timespan start="1043514000" end="1043526410">2003-01-25 12:00:00 EST - 2003-01-25 15:26:50 EST</lire:timespan> <lire:section> <lire:title>All Files</lire:title> <lire:subreport type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="File" max-chars="20" avg-chars="17"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="request_total" missing-cases="0">24</lire:value> <lire:value col="request_ratio" missing-cases="0" value="24">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:value col="request_total" missing-cases="0">3</lire:value> <lire:value col="request_ratio" missing-cases="0" value="3">12.5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">4.2</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">4.2</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="8"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0" value="9037995">8.6M</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="9037995">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/movies</lire:name> <lire:value col="bytes_total" missing-cases="0" value="8530453">8.1M</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="8530453">94.4</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" missing-cases="0" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">5.6</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="downloads-by-period" superservice="test" schemas="test"> <lire:title>Download by 15m Period</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timegroup:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="16" label="Period" max-chars="16" avg-chars="15"/> <lire:column-info name="download_count" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="download_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> <lire:column-info name="user_count" class="numerical" type="int" col-start="3" col-end="3" col-width="12" label="Unique Users" max-chars="12" avg-chars="3"/> <lire:column-info name="user_ratio" class="numerical" type="int" col-start="4" col-end="4" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="download_count" missing-cases="0">24</lire:value> <lire:value col="download_ratio" missing-cases="0" value="24">100.0</lire:value> <lire:value col="user_count" missing-cases="0">5</lire:value> <lire:value col="user_ratio" missing-cases="0" value="5">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timegroup:time_start" value="1043514000" range="900">2003-01-25 12:00</lire:name> <lire:value col="download_count" missing-cases="0">4</lire:value> <lire:value col="download_ratio" missing-cases="0" value="4">16.7</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timegroup:time_start" value="1043514900" range="900"> 12:15</lire:name> <lire:value col="download_count" missing-cases="0">11</lire:value> <lire:value col="download_ratio" missing-cases="0" value="11">45.8</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="timegroup:time_start" value="1043515800" range="900"> 12:30</lire:name> <lire:value col="download_count" missing-cases="0">6</lire:value> <lire:value col="download_ratio" missing-cases="0" value="6">25.0</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="timegroup:time_start" value="1043516700" range="900"> 12:45</lire:name> <lire:value col="download_count" missing-cases="0">2</lire:value> <lire:value col="download_ratio" missing-cases="0" value="2">8.3</lire:value> <lire:value col="user_count" missing-cases="0">1</lire:value> <lire:value col="user_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="timegroup:time_start" value="1043525700" range="900"> 15:15</lire:name> <lire:value col="download_count" missing-cases="0">1</lire:value> <lire:value col="download_ratio" missing-cases="0" value="1">4.2</lire:value> <lire:value col="user_count" missing-cases="0">1</lire:value> <lire:value col="user_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>JPEG Files</lire:title> <lire:description><para>Applied filter in this section: selected files matching .*.jpg$</para> </lire:description> <lire:subreport type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="File" max-chars="20" avg-chars="18"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="19" missing-cases="0"> <lire:value col="request_total" missing-cases="0">19</lire:value> <lire:value col="request_ratio" missing-cases="0" value="19">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:value col="request_total" missing-cases="0">1</lire:value> <lire:value col="request_ratio" missing-cases="0" value="1">5.3</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="10"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="6"/> </lire:table-info> <lire:group-summary nrecords="19" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" missing-cases="0" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="507542">100.0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Sessions</lire:title> <lire:subreport type="sessions-by-length" superservice="test" schemas="test-derived"> <lire:title>Sessions by Length</lire:title> <lire:table> <lire:table-info> <lire:column-info name="rangegroup:session_length" class="categorical" type="duration" col-start="0" col-end="0" col-width="9" label="Length" max-chars="9" avg-chars="8"/> <lire:column-info name="sessions_count" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="2"/> <lire:column-info name="sessions_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="5" missing-cases="0"> <lire:value col="sessions_count" missing-cases="0">5</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="5">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="rangegroup:session_length" value="0" range="60">[0s-1m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="rangegroup:session_length" value="60" range="60">[1m-2m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="rangegroup:session_length" value="300" range="60">[5m-6m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="rangegroup:session_length" value="360" range="60">[6m-7m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="rangegroup:session_length" value="2700" range="60">[45m-46m></lire:name> <lire:value col="sessions_count" missing-cases="0">1</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="1">20.0</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="sessions-by-user_class" superservice="test" schemas="test-derived"> <lire:title>Sessions by User Class</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user_class" class="categorical" type="string" col-start="0" col-end="0" col-width="10" label="user_class" max-chars="10" avg-chars="10"/> <lire:column-info name="sessions_total" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="5" missing-cases="5"> <lire:value col="sessions_total" missing-cases="0">5</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Download Reports</lire:title> <lire:subreport type="avg-file_size-by-timeslot" superservice="test" schemas="test"> <lire:title>Average File Size By 1h Timeslot</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timeslot:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="6" label="Length" max-chars="6" avg-chars="6"/> <lire:column-info name="avg_file_size" class="numerical" type="bytes" col-start="1" col-end="1" col-width="13" label="Avg File Size" max-chars="13" avg-chars="8"/> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="avg_file_size" missing-cases="0" total="9037995" n="24" value="376583.12">367.8k</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timeslot:time_start" value="2-12" range="1">12:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="6713494" n="23" value="291891.04">285.0k</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timeslot:time_start" value="2-15" range="1">15:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="2324501" n="1" value="2324501.00">2.2M</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="user_downloads-report" superservice="test" schemas="test"> <lire:title>User's Downloads Report</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user" class="categorical" type="string" col-start="0" col-end="3" col-width="2" label="Username" max-chars="8" avg-chars="7"/> <lire:column-info name="first_file" class="numerical" type="filename" col-start="4" col-end="4" col-width="20" label="First File" max-chars="20" avg-chars="18"/> <lire:column-info name="last_file" class="numerical" type="filename" col-start="5" col-end="5" col-width="20" label="Last File" max-chars="20" avg-chars="18"/> <lire:column-info name="min_file_size" class="numerical" type="bytes" col-start="6" col-end="6" col-width="8" label="Smallest" max-chars="8" avg-chars="6"/> <lire:column-info name="max_file_size" class="numerical" type="bytes" col-start="7" col-end="7" col-width="7" label="Largest" max-chars="7" avg-chars="5"/> <lire:group-info name="records:3" row-idx="1"> <lire:column-info name="time_start" class="categorical" type="timestamp" col-start="1" col-end="1" col-width="19" label="Start Time" max-chars="19" avg-chars="19"/> <lire:column-info name="file" class="categorical" type="filename" col-start="2" col-end="2" col-width="20" label="File" max-chars="20" avg-chars="19"/> <lire:column-info name="file_size" class="categorical" type="bytes" col-start="3" col-end="3" col-width="6" label="Size" max-chars="6" avg-chars="5"/> </lire:group-info> </lire:table-info> <lire:group-summary nrecords="24" missing-cases="0"> <lire:value col="first_file" missing-cases="0" total="1043514000">/pictures/000001.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="13245">12.9k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="user">bjoy</lire:name> <lire:value col="first_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="1" missing-cases="0" row-idx="0"> </lire:group-summary> <lire:entry row-idx="1"> <lire:name col="time_start" value="1043526410">2003-01-25 15:26:50</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="2"> <lire:name col="user">flacoste</lire:name> <lire:value col="first_file" missing-cases="0" total="1043514300">/movies/000002.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043515075">/movies/000003.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="232450">227.0k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="1324500">1.3M</lire:value> <lire:group> <lire:group-summary nrecords="2" missing-cases="0" row-idx="2"> </lire:group-summary> <lire:entry row-idx="3"> <lire:name col="time_start" value="1043514300">2003-01-25 12:05:00</lire:name> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:name col="file_size" value="1324500">1.3M</lire:name> </lire:entry> <lire:entry row-idx="4"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:name col="file_size" value="232450">227.0k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="5"> <lire:name col="user">francis</lire:name> <lire:value col="first_file" missing-cases="0" total="1043514000">/pictures/000001.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043515075">/pictures/000019.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="13245">12.9k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="13" missing-cases="0" row-idx="5"> </lire:group-summary> <lire:entry row-idx="6"> <lire:name col="time_start" value="1043514000">2003-01-25 12:00:00</lire:name> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:name col="file_size" value="13245">12.9k</lire:name> </lire:entry> <lire:entry row-idx="7"> <lire:name col="time_start" value="1043514305">2003-01-25 12:05:05</lire:name> <lire:name col="file">/pictures/001001.jpg</lire:name> <lire:name col="file_size" value="16432">16.0k</lire:name> </lire:entry> <lire:entry row-idx="8"> <lire:name col="time_start" value="1043514400">2003-01-25 12:06:40</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="9"> <lire:name col="time_start" value="1043515000">2003-01-25 12:16:40</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="10"> <lire:name col="time_start" value="1043515006">2003-01-25 12:16:46</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="11"> <lire:name col="time_start" value="1043515010">2003-01-25 12:16:50</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="12"> <lire:name col="time_start" value="1043515015">2003-01-25 12:16:55</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="13"> <lire:name col="time_start" value="1043515020">2003-01-25 12:17:00</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="14"> <lire:name col="time_start" value="1043515027">2003-01-25 12:17:07</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="15"> <lire:name col="time_start" value="1043515038">2003-01-25 12:17:18</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="16"> <lire:name col="time_start" value="1043515050">2003-01-25 12:17:30</lire:name> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="17"> <lire:name col="time_start" value="1043515057">2003-01-25 12:17:37</lire:name> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:name col="file_size" value="56345">55.0k</lire:name> </lire:entry> <lire:entry row-idx="18"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/pictures/000019.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="19"> <lire:name col="user">joostvb</lire:name> <lire:value col="first_file" missing-cases="0" total="1043516010">/pictures/000012.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043516037">/pictures/000016.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:group> <lire:group-summary nrecords="5" missing-cases="0" row-idx="19"> </lire:group-summary> <lire:entry row-idx="20"> <lire:name col="time_start" value="1043516010">2003-01-25 12:33:30</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="21"> <lire:name col="time_start" value="1043516015">2003-01-25 12:33:35</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="22"> <lire:name col="time_start" value="1043516020">2003-01-25 12:33:40</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="23"> <lire:name col="time_start" value="1043516027">2003-01-25 12:33:47</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="24"> <lire:name col="time_start" value="1043516037">2003-01-25 12:33:57</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="25"> <lire:name col="user">wdankers</lire:name> <lire:value col="first_file" missing-cases="0" total="1043516400">/movies/001145.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043516705">/pictures/000011.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="3" missing-cases="0" row-idx="25"> </lire:group-summary> <lire:entry row-idx="26"> <lire:name col="time_start" value="1043516400">2003-01-25 12:40:00</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="27"> <lire:name col="time_start" value="1043516701">2003-01-25 12:45:01</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="28"> <lire:name col="time_start" value="1043516705">2003-01-25 12:45:05</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> </lire:table> </lire:subreport> </lire:section> </lire:report> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-merge.xml��������������������������������������������������������0000644�0001750�0001750�00000132552�10460672600�015567� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="us-ascii"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "http://www.logreport.org/LRML/2.1/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" version="2.1"> <!-- generated by Lire::Report(3pm) --> <lire:date time="1043632474">2003-01-26 20:54:34 EST</lire:date> <lire:timespan start="1043514000" end="1043526410">2003-01-25 12:00:00 EST - 2003-01-25 15:26:50 EST</lire:timespan> <lire:section> <lire:title>All Files</lire:title> <lire:subreport type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="File" max-chars="20" avg-chars="17"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="24"> <lire:value col="request_total">24</lire:value> <lire:value col="request_ratio" value="24">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:value col="request_total">3</lire:value> <lire:value col="request_ratio" value="3">12.5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">8.3</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:value col="request_total">1</lire:value> <lire:value col="request_ratio" value="1">4.2</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:value col="request_total">1</lire:value> <lire:value col="request_ratio" value="1">4.2</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="8"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="24"> <lire:value col="bytes_total" value="9037995">8.6M</lire:value> <lire:value col="bytes_ratio" value="9037995">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/movies</lire:name> <lire:value col="bytes_total" value="8530453">8.1M</lire:value> <lire:value col="bytes_ratio" value="8530453">94.4</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" value="507542">5.6</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="downloads-by-period" superservice="test" schemas="test"> <lire:title>Download by 15m Period</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timegroup:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="16" label="Period" max-chars="16" avg-chars="16"/> <lire:column-info name="download_count" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="2"/> <lire:column-info name="download_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> <lire:column-info name="user_count" class="numerical" type="int" col-start="3" col-end="3" col-width="12" label="Unique Users" max-chars="12" avg-chars="2"/> <lire:column-info name="user_ratio" class="numerical" type="int" col-start="4" col-end="4" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="24"> <lire:value col="download_count">24</lire:value> <lire:value col="download_ratio" value="24">100.0</lire:value> <lire:value col="user_count">5</lire:value> <lire:value col="user_ratio" value="5">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timegroup:time_start" value="1043514000" range="900">2003-01-25 12:00</lire:name> <lire:value col="download_count">4</lire:value> <lire:value col="download_ratio" value="4">16.7</lire:value> <lire:value col="user_count">2</lire:value> <lire:value col="user_ratio" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timegroup:time_start" value="1043514900" range="900"> 12:15</lire:name> <lire:value col="download_count">11</lire:value> <lire:value col="download_ratio" value="11">45.8</lire:value> <lire:value col="user_count">2</lire:value> <lire:value col="user_ratio" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="timegroup:time_start" value="1043515800" range="900"> 12:30</lire:name> <lire:value col="download_count">6</lire:value> <lire:value col="download_ratio" value="6">25.0</lire:value> <lire:value col="user_count">2</lire:value> <lire:value col="user_ratio" value="2">40.0</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="timegroup:time_start" value="1043516700" range="900"> 12:45</lire:name> <lire:value col="download_count">2</lire:value> <lire:value col="download_ratio" value="2">8.3</lire:value> <lire:value col="user_count">1</lire:value> <lire:value col="user_ratio" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="timegroup:time_start" value="1043517600" range="900"> 13:00</lire:name> <lire:value col="download_count">0</lire:value> <lire:value col="download_ratio" value="0">0.0</lire:value> <lire:value col="user_count">0</lire:value> <lire:value col="user_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="5"> <lire:name col="timegroup:time_start" value="1043518500" range="900"> 13:15</lire:name> <lire:value col="download_count">0</lire:value> <lire:value col="download_ratio" value="0">0.0</lire:value> <lire:value col="user_count">0</lire:value> <lire:value col="user_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="6"> <lire:name col="timegroup:time_start" value="1043519400" range="900"> 13:30</lire:name> <lire:value col="download_count">0</lire:value> <lire:value col="download_ratio" value="0">0.0</lire:value> <lire:value col="user_count">0</lire:value> <lire:value col="user_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="7"> <lire:name col="timegroup:time_start" value="1043520300" range="900"> 13:45</lire:name> <lire:value col="download_count">0</lire:value> <lire:value col="download_ratio" value="0">0.0</lire:value> <lire:value col="user_count">0</lire:value> <lire:value col="user_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="8"> <lire:name col="timegroup:time_start" value="1043521200" range="900"> 14:00</lire:name> <lire:value col="download_count">0</lire:value> <lire:value col="download_ratio" value="0">0.0</lire:value> <lire:value col="user_count">0</lire:value> <lire:value col="user_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="9"> <lire:name col="timegroup:time_start" value="1043522100" range="900"> 14:15</lire:name> <lire:value col="download_count">0</lire:value> <lire:value col="download_ratio" value="0">0.0</lire:value> <lire:value col="user_count">0</lire:value> <lire:value col="user_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="10"> <lire:name col="timegroup:time_start" value="1043523000" range="900"> 14:30</lire:name> <lire:value col="download_count">0</lire:value> <lire:value col="download_ratio" value="0">0.0</lire:value> <lire:value col="user_count">0</lire:value> <lire:value col="user_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="11"> <lire:name col="timegroup:time_start" value="1043523900" range="900"> 14:45</lire:name> <lire:value col="download_count">0</lire:value> <lire:value col="download_ratio" value="0">0.0</lire:value> <lire:value col="user_count">0</lire:value> <lire:value col="user_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="12"> <lire:name col="timegroup:time_start" value="1043524800" range="900"> 15:00</lire:name> <lire:value col="download_count">0</lire:value> <lire:value col="download_ratio" value="0">0.0</lire:value> <lire:value col="user_count">0</lire:value> <lire:value col="user_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="13"> <lire:name col="timegroup:time_start" value="1043525700" range="900"> 15:15</lire:name> <lire:value col="download_count">1</lire:value> <lire:value col="download_ratio" value="1">4.2</lire:value> <lire:value col="user_count">1</lire:value> <lire:value col="user_ratio" value="1">20.0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>JPEG Files</lire:title> <lire:description><para>Applied filter in this section: selected files matching .*.jpg$</para> </lire:description> <lire:subreport type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="File" max-chars="20" avg-chars="18"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="19"> <lire:value col="request_total">19</lire:value> <lire:value col="request_ratio" value="19">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">10.5</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total">2</lire:value> <lire:value col="request_ratio" value="2">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:value col="request_total">1</lire:value> <lire:value col="request_ratio" value="1">5.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:value col="request_total">1</lire:value> <lire:value col="request_ratio" value="1">5.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:value col="request_total">1</lire:value> <lire:value col="request_ratio" value="1">5.3</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="10"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="6"/> </lire:table-info> <lire:group-summary nrecords="19"> <lire:value col="bytes_total" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" value="507542">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" value="507542">495.6k</lire:value> <lire:value col="bytes_ratio" value="507542">100.0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Sessions</lire:title> <lire:subreport type="sessions-by-length" superservice="test" schemas="test-derived"> <lire:title>Sessions by Length</lire:title> <lire:table> <lire:table-info> <lire:column-info name="rangegroup:session_length" class="categorical" type="duration" col-start="0" col-end="0" col-width="9" label="Length" max-chars="9" avg-chars="9"/> <lire:column-info name="sessions_count" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="2"/> <lire:column-info name="sessions_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="5"> <lire:value col="sessions_count">5</lire:value> <lire:value col="sessions_ratio" value="5">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="rangegroup:session_length" value="0" range="60">[0s-1m></lire:name> <lire:value col="sessions_count">1</lire:value> <lire:value col="sessions_ratio" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="rangegroup:session_length" value="60" range="60">[1m-2m></lire:name> <lire:value col="sessions_count">1</lire:value> <lire:value col="sessions_ratio" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="rangegroup:session_length" value="120" range="60">[2m-3m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="rangegroup:session_length" value="180" range="60">[3m-4m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="rangegroup:session_length" value="240" range="60">[4m-5m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="5"> <lire:name col="rangegroup:session_length" value="300" range="60">[5m-6m></lire:name> <lire:value col="sessions_count">1</lire:value> <lire:value col="sessions_ratio" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="6"> <lire:name col="rangegroup:session_length" value="360" range="60">[6m-7m></lire:name> <lire:value col="sessions_count">1</lire:value> <lire:value col="sessions_ratio" value="1">20.0</lire:value> </lire:entry> <lire:entry row-idx="7"> <lire:name col="rangegroup:session_length" value="420" range="60">[7m-8m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="8"> <lire:name col="rangegroup:session_length" value="480" range="60">[8m-9m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="9"> <lire:name col="rangegroup:session_length" value="540" range="60">[9m-10m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="10"> <lire:name col="rangegroup:session_length" value="600" range="60">[10m-11m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="11"> <lire:name col="rangegroup:session_length" value="660" range="60">[11m-12m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="12"> <lire:name col="rangegroup:session_length" value="720" range="60">[12m-13m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="13"> <lire:name col="rangegroup:session_length" value="780" range="60">[13m-14m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="14"> <lire:name col="rangegroup:session_length" value="840" range="60">[14m-15m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="15"> <lire:name col="rangegroup:session_length" value="900" range="60">[15m-16m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="16"> <lire:name col="rangegroup:session_length" value="960" range="60">[16m-17m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="17"> <lire:name col="rangegroup:session_length" value="1020" range="60">[17m-18m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="18"> <lire:name col="rangegroup:session_length" value="1080" range="60">[18m-19m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="19"> <lire:name col="rangegroup:session_length" value="1140" range="60">[19m-20m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="20"> <lire:name col="rangegroup:session_length" value="1200" range="60">[20m-21m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="21"> <lire:name col="rangegroup:session_length" value="1260" range="60">[21m-22m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="22"> <lire:name col="rangegroup:session_length" value="1320" range="60">[22m-23m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="23"> <lire:name col="rangegroup:session_length" value="1380" range="60">[23m-24m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="24"> <lire:name col="rangegroup:session_length" value="1440" range="60">[24m-25m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="25"> <lire:name col="rangegroup:session_length" value="1500" range="60">[25m-26m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="26"> <lire:name col="rangegroup:session_length" value="1560" range="60">[26m-27m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="27"> <lire:name col="rangegroup:session_length" value="1620" range="60">[27m-28m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="28"> <lire:name col="rangegroup:session_length" value="1680" range="60">[28m-29m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="29"> <lire:name col="rangegroup:session_length" value="1740" range="60">[29m-30m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="30"> <lire:name col="rangegroup:session_length" value="1800" range="60">[30m-31m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="31"> <lire:name col="rangegroup:session_length" value="1860" range="60">[31m-32m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="32"> <lire:name col="rangegroup:session_length" value="1920" range="60">[32m-33m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="33"> <lire:name col="rangegroup:session_length" value="1980" range="60">[33m-34m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="34"> <lire:name col="rangegroup:session_length" value="2040" range="60">[34m-35m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="35"> <lire:name col="rangegroup:session_length" value="2100" range="60">[35m-36m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="36"> <lire:name col="rangegroup:session_length" value="2160" range="60">[36m-37m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="37"> <lire:name col="rangegroup:session_length" value="2220" range="60">[37m-38m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="38"> <lire:name col="rangegroup:session_length" value="2280" range="60">[38m-39m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="39"> <lire:name col="rangegroup:session_length" value="2340" range="60">[39m-40m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="40"> <lire:name col="rangegroup:session_length" value="2400" range="60">[40m-41m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="41"> <lire:name col="rangegroup:session_length" value="2460" range="60">[41m-42m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="42"> <lire:name col="rangegroup:session_length" value="2520" range="60">[42m-43m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="43"> <lire:name col="rangegroup:session_length" value="2580" range="60">[43m-44m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="44"> <lire:name col="rangegroup:session_length" value="2640" range="60">[44m-45m></lire:name> <lire:value col="sessions_count">0</lire:value> <lire:value col="sessions_ratio" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="45"> <lire:name col="rangegroup:session_length" value="2700" range="60">[45m-46m></lire:name> <lire:value col="sessions_count">1</lire:value> <lire:value col="sessions_ratio" value="1">20.0</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="sessions-by-user_class" superservice="test" schemas="test-derived"> <lire:title>Sessions by User Class</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user_class" class="categorical" type="string" col-start="0" col-end="0" col-width="10" label="user_class" max-chars="10" avg-chars="10"/> <lire:column-info name="sessions_total" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="5" missing-cases="5"> <lire:value col="sessions_total" missing-cases="0">5</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Download Reports</lire:title> <lire:subreport type="avg-file_size-by-timeslot" superservice="test" schemas="test"> <lire:title>Average File Size By 1h Timeslot</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timeslot:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="6" label="Length" max-chars="6" avg-chars="6"/> <lire:column-info name="avg_file_size" class="numerical" type="bytes" col-start="1" col-end="1" col-width="13" label="Avg File Size" max-chars="13" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="24"> <lire:value col="avg_file_size" total="9037995" n="24" value="376583.12">367.8k</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timeslot:time_start" value="2-0" range="1">00:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timeslot:time_start" value="2-1" range="1">01:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="timeslot:time_start" value="2-2" range="1">02:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="timeslot:time_start" value="2-3" range="1">03:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="timeslot:time_start" value="2-4" range="1">04:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="5"> <lire:name col="timeslot:time_start" value="2-5" range="1">05:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="6"> <lire:name col="timeslot:time_start" value="2-6" range="1">06:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="7"> <lire:name col="timeslot:time_start" value="2-7" range="1">07:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="8"> <lire:name col="timeslot:time_start" value="2-8" range="1">08:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="9"> <lire:name col="timeslot:time_start" value="2-9" range="1">09:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="10"> <lire:name col="timeslot:time_start" value="2-10" range="1">10:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="11"> <lire:name col="timeslot:time_start" value="2-11" range="1">11:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="12"> <lire:name col="timeslot:time_start" value="2-12" range="1">12:00</lire:name> <lire:value col="avg_file_size" total="6713494" n="23" value="291891.04">285.0k</lire:value> </lire:entry> <lire:entry row-idx="13"> <lire:name col="timeslot:time_start" value="2-13" range="1">13:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="14"> <lire:name col="timeslot:time_start" value="2-14" range="1">14:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="15"> <lire:name col="timeslot:time_start" value="2-15" range="1">15:00</lire:name> <lire:value col="avg_file_size" total="2324501" n="1" value="2324501.00">2.2M</lire:value> </lire:entry> <lire:entry row-idx="16"> <lire:name col="timeslot:time_start" value="2-16" range="1">16:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="17"> <lire:name col="timeslot:time_start" value="2-17" range="1">17:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="18"> <lire:name col="timeslot:time_start" value="2-18" range="1">18:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="19"> <lire:name col="timeslot:time_start" value="2-19" range="1">19:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="20"> <lire:name col="timeslot:time_start" value="2-20" range="1">20:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="21"> <lire:name col="timeslot:time_start" value="2-21" range="1">21:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="22"> <lire:name col="timeslot:time_start" value="2-22" range="1">22:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="23"> <lire:name col="timeslot:time_start" value="2-23" range="1">23:00</lire:name> <lire:value col="avg_file_size" total="0" n="0">NaN</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="user_downloads-report" superservice="test" schemas="test"> <lire:title>User's Downloads Report</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user" class="categorical" type="string" col-start="0" col-end="3" col-width="2" label="Username" max-chars="8" avg-chars="7"/> <lire:column-info name="first_file" class="numerical" type="filename" col-start="4" col-end="4" col-width="20" label="First File" max-chars="20" avg-chars="18"/> <lire:column-info name="last_file" class="numerical" type="filename" col-start="5" col-end="5" col-width="20" label="Last File" max-chars="20" avg-chars="18"/> <lire:column-info name="min_file_size" class="numerical" type="bytes" col-start="6" col-end="6" col-width="8" label="Smallest" max-chars="8" avg-chars="6"/> <lire:column-info name="max_file_size" class="numerical" type="bytes" col-start="7" col-end="7" col-width="7" label="Largest" max-chars="7" avg-chars="5"/> <lire:group-info name="records:3" row-idx="1"> <lire:column-info name="time_start" class="categorical" type="timestamp" col-start="1" col-end="1" col-width="19" label="Start Time" max-chars="19" avg-chars="19"/> <lire:column-info name="file" class="categorical" type="filename" col-start="2" col-end="2" col-width="20" label="File" max-chars="20" avg-chars="19"/> <lire:column-info name="file_size" class="categorical" type="bytes" col-start="3" col-end="3" col-width="6" label="Size" max-chars="6" avg-chars="5"/> </lire:group-info> </lire:table-info> <lire:group-summary nrecords="24"> <lire:value col="first_file" total="1043514000">/pictures/000001.jpg</lire:value> <lire:value col="last_file" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="min_file_size" value="13245">12.9k</lire:value> <lire:value col="max_file_size" value="2324501">2.2M</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="user">bjoy</lire:name> <lire:value col="first_file" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="last_file" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="min_file_size" value="2324501">2.2M</lire:value> <lire:value col="max_file_size" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="1" row-idx="0"> </lire:group-summary> <lire:entry row-idx="1"> <lire:name col="time_start" value="1043526410">2003-01-25 15:26:50</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="2"> <lire:name col="user">flacoste</lire:name> <lire:value col="first_file" total="1043514300">/movies/000002.mpg</lire:value> <lire:value col="last_file" total="1043515075">/movies/000003.mpg</lire:value> <lire:value col="min_file_size" value="232450">227.0k</lire:value> <lire:value col="max_file_size" value="1324500">1.3M</lire:value> <lire:group> <lire:group-summary nrecords="2" row-idx="2"> </lire:group-summary> <lire:entry row-idx="3"> <lire:name col="time_start" value="1043514300">2003-01-25 12:05:00</lire:name> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:name col="file_size" value="1324500">1.3M</lire:name> </lire:entry> <lire:entry row-idx="4"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:name col="file_size" value="232450">227.0k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="5"> <lire:name col="user">francis</lire:name> <lire:value col="first_file" total="1043514000">/pictures/000001.jpg</lire:value> <lire:value col="last_file" total="1043515075">/pictures/000019.jpg</lire:value> <lire:value col="min_file_size" value="13245">12.9k</lire:value> <lire:value col="max_file_size" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="13" row-idx="5"> </lire:group-summary> <lire:entry row-idx="6"> <lire:name col="time_start" value="1043514000">2003-01-25 12:00:00</lire:name> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:name col="file_size" value="13245">12.9k</lire:name> </lire:entry> <lire:entry row-idx="7"> <lire:name col="time_start" value="1043514305">2003-01-25 12:05:05</lire:name> <lire:name col="file">/pictures/001001.jpg</lire:name> <lire:name col="file_size" value="16432">16.0k</lire:name> </lire:entry> <lire:entry row-idx="8"> <lire:name col="time_start" value="1043514400">2003-01-25 12:06:40</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="9"> <lire:name col="time_start" value="1043515000">2003-01-25 12:16:40</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="10"> <lire:name col="time_start" value="1043515006">2003-01-25 12:16:46</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="11"> <lire:name col="time_start" value="1043515010">2003-01-25 12:16:50</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="12"> <lire:name col="time_start" value="1043515015">2003-01-25 12:16:55</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="13"> <lire:name col="time_start" value="1043515020">2003-01-25 12:17:00</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="14"> <lire:name col="time_start" value="1043515027">2003-01-25 12:17:07</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="15"> <lire:name col="time_start" value="1043515038">2003-01-25 12:17:18</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="16"> <lire:name col="time_start" value="1043515050">2003-01-25 12:17:30</lire:name> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="17"> <lire:name col="time_start" value="1043515057">2003-01-25 12:17:37</lire:name> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:name col="file_size" value="56345">55.0k</lire:name> </lire:entry> <lire:entry row-idx="18"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/pictures/000019.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="19"> <lire:name col="user">joostvb</lire:name> <lire:value col="first_file" total="1043516010">/pictures/000012.jpg</lire:value> <lire:value col="last_file" total="1043516037">/pictures/000016.jpg</lire:value> <lire:value col="min_file_size" value="26345">25.7k</lire:value> <lire:value col="max_file_size" value="26345">25.7k</lire:value> <lire:group> <lire:group-summary nrecords="5" row-idx="19"> </lire:group-summary> <lire:entry row-idx="20"> <lire:name col="time_start" value="1043516010">2003-01-25 12:33:30</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="21"> <lire:name col="time_start" value="1043516015">2003-01-25 12:33:35</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="22"> <lire:name col="time_start" value="1043516020">2003-01-25 12:33:40</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="23"> <lire:name col="time_start" value="1043516027">2003-01-25 12:33:47</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="24"> <lire:name col="time_start" value="1043516037">2003-01-25 12:33:57</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="25"> <lire:name col="user">wdankers</lire:name> <lire:value col="first_file" total="1043516400">/movies/001145.mpg</lire:value> <lire:value col="last_file" total="1043516705">/pictures/000011.jpg</lire:value> <lire:value col="min_file_size" value="26345">25.7k</lire:value> <lire:value col="max_file_size" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="3" row-idx="25"> </lire:group-summary> <lire:entry row-idx="26"> <lire:name col="time_start" value="1043516400">2003-01-25 12:40:00</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="27"> <lire:name col="time_start" value="1043516701">2003-01-25 12:45:01</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="28"> <lire:name col="time_start" value="1043516705">2003-01-25 12:45:05</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> </lire:table> </lire:subreport> </lire:section> </lire:report> ������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/jobs-config.xml�������������������������������������������������������0000644�0001750�0001750�00000013430�10460672600�015704� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE config PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Markup Language V1.0//EN" "http://www.logreport.org/LRCML/1.0/lrcml.dtd"[ <!ENTITY % LRCML.pfx ""> <!ENTITY % xmlns.colon ""> ]> <config xmlns="http://www.logreport.org/LRCML/"> <global> <param name="lr_week_numbering">ISO</param> <param name="streams_config"> <param name="test"> <param name="keep_days">1</param> </param> <param name="test-derived"> <param name="test-extended" value="none"> </param> </param> <param name="test-extended" /> </param> <param name="report_jobs"> <param name="report_job"> <param name="name">Test_Report</param> <param name="schedules"> <param name="schedule"> <param name="output_jobs"> <param name="output_job"> <param name="format" value="pdf" /> <param name="destination" value="email"> <param name="subject">PDF Report</param> <param name="emails"> <param name="email">flacoste@logreport.org</param> </param> </param> <param name="name">PDF</param> </param> </param> <param name="period">daily</param> <param name="report_config">test.cfg</param> </param> <param name="schedule"> <param name="output_jobs"> <param name="output_job"> <param name="format" value="html" /> <param name="destination" value="file"> <param name="file">report %Y-W%V</param> </param> <param name="name">HTML</param> </param> <param name="output_job"> <param name="format" value="txt"> <param name="encoding" /> </param> <param name="destination" value="email"> <param name="subject">Text Report</param> <param name="emails"> <param name="email">wolfgang@logreport.org</param> </param> </param> <param name="name">Text Email</param> </param> </param> <param name="period">weekly</param> <param name="report_config">test.cfg</param> </param> </param> </param> </param> <param name="import_jobs"> <param name="import_job"> <param name="period">daily</param> <param name="filter"></param> <param name="name">Daily Import</param> <param name="log_encoding"></param> <param name="log_file">test.dlf</param> <param name="service" value="test_newapi"> </param> </param> </param> <param name="reports"> <param name="report_cfg"> <param name="id" value="test.cfg"/> <param name="sections"> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="All Files" /> <param name="specs"> <param name="test:top-files"> <param name="id" value="top-files.0" /> <param name="files_to_show" value="5" /> </param> <param name="test:top-dirs"> <param name="id" value="top-dirs.0" /> <param name="dirs_to_show" value="5" /> </param> <param name="test:downloads-by-period"> <param name="id" value="downloads-by-period.0" /> <param name="period" value="15m" /> <param name="charts"> <param name="chart"> <param name="title" value="Users and Downloads by 15m" /> <param name="case_var" value="timegroup:time_start" /> <param name="type" value="vbars"> <param name="y" value="download_count" /> <param name="y2" value="user_count" /> </param> </param> </param> </param> </param> </param> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="JPEG Files" /> <param name="filters"> <param name="test:select-file"> <param name="id" value="select-file.0" /> <param name="file_match" value=".*.jpg$" /> </param> </param> <param name="specs"> <param name="test:top-files"> <param name="id" value="top-files.1" /> <param name="files_to_show" value="5" /> </param> <param name="test:top-dirs"> <param name="id" value="top-dirs.1" /> <param name="dirs_to_show" value="5" /> </param> </param> </param> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="Sessions" /> <param name="specs"> <param name="test:sessions-by-length"> <param name="id" value="sessions-by-length.0" /> </param> <param name="test:sessions-by-user_class"> <param name="id" value="sessions-by-user_class.0" /> </param> </param> </param> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="Download Reports" /> <param name="specs"> <param name="test:avg-file_size-by-timeslot"> <param name="id" value="avg-file_size-by-timeslot.0" /> </param> <param name="test:user_downloads-report"> <param name="id" value="user_downloads-report.0" /> </param> </param> </param> </param> </param> </param> </global> </config> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-utf-16le.txt�����������������������������������������������������0000644�0001750�0001750�00000003012�10460672601�016037� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������R�e�p�o�r�t� �g�e�n�e�r�a�t�e�d�:� �2�0�0�4�-�0�8�-�3�1� �0�0�:�3�0�:�4�9� �E�S�T� �R�e�p�o�r�t�i�n�g� �o�n� �p�e�r�i�o�d�:� �2�0�0�3�-�0�1�-�2�5� �1�2�:�1�6�:�4�6� �E�S�T� �-� �2�0�0�3�-�0�1�-�2�5� �1�2�:�4�5�:�0�5� �E�S�T� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �T��l��c�h�a�r�g�e�m�e�n�t�s� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �-�-�-�-�-�-�-�-�-�-�-�-�-�-�-� � � � � � �F�i�l�t�r�e� �a�p�p�l�i�q�u�� �� �c�e�t�t�e� �s�e�c�t�i�o�n�:� �E�n�r�e�g�i�s�t�r�e�m�e�n�t�s� �D�L�F� �p�o�u�r� � � � � �2�0�0�3�-�0�1�-�2�5�.� � � � �T��l��c�h�a�r�g�e�m�e�n�t�s� �p�a�r� �u�s�a�g�e�r�,� �T�o�p� �5� � � � �U�s�a�g�e�r� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �T��l��c�h�a�r�g�e�m�e�n�t�s� �%� �t�o�t�a�l� � � �-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-� �-�-�-�-�-�-�-�-�-�-�-�-�-�-�-� �-�-�-�-�-�-�-� � � �f�r�a�n��o�i�s� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �2� � � � �5�0�.�0� � � �h��l��n�e� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �2� � � � �5�0�.�0� � � �-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-� �-�-�-�-�-�-�-�-�-�-�-�-�-�-�-� �-�-�-�-�-�-�-� � � �T�o�t�a�l� �f�o�r� �4� �r�e�c�o�r�d�s� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �4� � � �1�0�0�.�0� � � �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/jobs-config-15-migrated.xml�������������������������������������������0000644�0001750�0001750�00000012550�10460672600�017723� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE config PUBLIC "-//LogReport.ORG//DTD Lire Report Configuration Markup Language V1.0//EN" "http://www.logreport.org/LRCML/1.0/lrcml.dtd"[ <!ENTITY % LRCML.pfx ""> <!ENTITY % xmlns.colon ""> ]> <config xmlns="http://www.logreport.org/LRCML/"> <global> <param name="lr_week_numbering">ISO</param> <param name="streams_config"> <param name="test"> <param name="keep_days">1</param> </param> <param name="test-derived"> <param name="test-extended" value="none"> </param> </param> <param name="test-extended" /> </param> <param name="report_jobs"> <param name="report_job"> <param name="name">Test_Report</param> <param name="schedules"> <param name="schedule"> <param name="output_jobs"> <param name="output_job"> <param name="format" value="pdf" /> <param name="destination" value="email"> <param name="subject">PDF Report</param> <param name="emails"> <param name="email">flacoste@logreport.org</param> </param> </param> <param name="name">PDF</param> </param> </param> <param name="period">daily</param> <param name="report_config">test.cfg</param> </param> <param name="schedule"> <param name="output_jobs"> <param name="output_job"> <param name="format" value="html" /> <param name="destination" value="file"> <param name="file">report %Y-W%V</param> </param> <param name="name">HTML</param> </param> <param name="output_job"> <param name="format" value="txt"> <param name="encoding" /> </param> <param name="destination" value="email"> <param name="subject">Text Report</param> <param name="emails"> <param name="email">wolfgang@logreport.org</param> </param> </param> <param name="name">Text Email</param> </param> </param> <param name="period">weekly</param> <param name="report_config">test.cfg</param> </param> </param> </param> </param> <param name="import_jobs"> <param name="import_job"> <param name="period">daily</param> <param name="filter"></param> <param name="name">Daily Import</param> <param name="log_encoding"></param> <param name="log_file">test.dlf</param> <param name="service" value="test_newapi"> </param> </param> </param> <param name="reports"> <param name="report_cfg"> <param name="id" value="test.cfg"/> <param name="sections"> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="All Files" /> <param name="specs"> <param name="test:top-files"> <param name="id" value="top-files.0" /> <param name="files_to_show" value="5" /> </param> <param name="test:top-dirs"> <param name="id" value="top-dirs.0" /> <param name="dirs_to_show" value="5" /> </param> <param name="test:downloads-by-period"> <param name="id" value="downloads-by-period.0" /> <param name="period" value="15m" /> </param> </param> </param> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="JPEG Files" /> <param name="filters"> <param name="test:select-file"> <param name="id" value="select-file.0" /> <param name="file_match" value=".*.jpg$" /> </param> </param> <param name="specs"> <param name="test:top-files"> <param name="id" value="top-files.1" /> <param name="files_to_show" value="5" /> </param> <param name="test:top-dirs"> <param name="id" value="top-dirs.1" /> <param name="dirs_to_show" value="5" /> </param> </param> </param> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="Sessions" /> <param name="specs"> <param name="test:sessions-by-length"> <param name="id" value="sessions-by-length.0" /> </param> <param name="test:sessions-by-user_class"> <param name="id" value="sessions-by-user_class.0" /> </param> </param> </param> <param name="section"> <param name="superservice" value="test" /> <param name="title" value="Download Reports" /> <param name="specs"> <param name="test:avg-file_size-by-timeslot"> <param name="id" value="avg-file_size-by-timeslot.0" /> </param> <param name="test:user_downloads-report"> <param name="id" value="user_downloads-report.0" /> </param> </param> </param> </param> </param> </param> </global> </config> ��������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/data/test-doublemerge.xml��������������������������������������������������0000644�0001750�0001750�00000160566�10460672600�016770� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="us-ascii"?> <!DOCTYPE lire:report PUBLIC "-//LogReport.ORG//DTD Lire Report Markup Language V2.1//EN" "http://www.logreport.org/LRML/2.1/lrml.dtd"> <lire:report xmlns:lire="http://www.logreport.org/LRML/" version="2.1"> <!-- generated by lr_xml_merge(1) --> <lire:date time="1045266513">2003-02-14 18:48:33 EST</lire:date> <lire:timespan start="1043514000" end="1043526410">2003-01-25 12:00:00 EST - 2003-01-25 15:26:50 EST</lire:timespan> <lire:section> <lire:title>All Files</lire:title> <lire:subreport type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="File" max-chars="20" avg-chars="17"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="48" missing-cases="0"> <lire:value col="request_total" missing-cases="0">48</lire:value> <lire:value col="request_ratio" missing-cases="0" value="48">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:value col="request_total" missing-cases="0">6</lire:value> <lire:value col="request_ratio" missing-cases="0" value="6">12.5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">8.3</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">8.3</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">8.3</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">8.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">4.2</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">4.2</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="8"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="48" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0" value="18075990">17.2M</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="18075990">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/movies</lire:name> <lire:value col="bytes_total" missing-cases="0" value="17060906">16.3M</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="17060906">94.4</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" missing-cases="0" value="1015084">991.3k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="1015084">5.6</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="downloads-by-period" superservice="test" schemas="test"> <lire:title>Download by 15m Period</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timegroup:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="16" label="Period" max-chars="16" avg-chars="16"/> <lire:column-info name="download_count" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="2"/> <lire:column-info name="download_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> <lire:column-info name="user_count" class="numerical" type="int" col-start="3" col-end="3" col-width="12" label="Unique Users" max-chars="12" avg-chars="2"/> <lire:column-info name="user_ratio" class="numerical" type="int" col-start="4" col-end="4" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="48" missing-cases="0"> <lire:value col="download_count" missing-cases="0">48</lire:value> <lire:value col="download_ratio" missing-cases="0" value="48">100.0</lire:value> <lire:value col="user_count" missing-cases="0">10</lire:value> <lire:value col="user_ratio" missing-cases="0" value="10">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timegroup:time_start" value="1043514000" range="900">2003-01-25 12:00</lire:name> <lire:value col="download_count" missing-cases="0">8</lire:value> <lire:value col="download_ratio" missing-cases="0" value="8">16.7</lire:value> <lire:value col="user_count" missing-cases="0">4</lire:value> <lire:value col="user_ratio" missing-cases="0" value="4">40.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timegroup:time_start" value="1043514900" range="900"> 12:15</lire:name> <lire:value col="download_count" missing-cases="0">22</lire:value> <lire:value col="download_ratio" missing-cases="0" value="22">45.8</lire:value> <lire:value col="user_count" missing-cases="0">4</lire:value> <lire:value col="user_ratio" missing-cases="0" value="4">40.0</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="timegroup:time_start" value="1043515800" range="900"> 12:30</lire:name> <lire:value col="download_count" missing-cases="0">12</lire:value> <lire:value col="download_ratio" missing-cases="0" value="12">25.0</lire:value> <lire:value col="user_count" missing-cases="0">4</lire:value> <lire:value col="user_ratio" missing-cases="0" value="4">40.0</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="timegroup:time_start" value="1043516700" range="900"> 12:45</lire:name> <lire:value col="download_count" missing-cases="0">4</lire:value> <lire:value col="download_ratio" missing-cases="0" value="4">8.3</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">20.0</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="timegroup:time_start" value="1043517600" range="900"> 13:00</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="5"> <lire:name col="timegroup:time_start" value="1043518500" range="900"> 13:15</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="6"> <lire:name col="timegroup:time_start" value="1043519400" range="900"> 13:30</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="7"> <lire:name col="timegroup:time_start" value="1043520300" range="900"> 13:45</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="8"> <lire:name col="timegroup:time_start" value="1043521200" range="900"> 14:00</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="9"> <lire:name col="timegroup:time_start" value="1043522100" range="900"> 14:15</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="10"> <lire:name col="timegroup:time_start" value="1043523000" range="900"> 14:30</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="11"> <lire:name col="timegroup:time_start" value="1043523900" range="900"> 14:45</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="12"> <lire:name col="timegroup:time_start" value="1043524800" range="900"> 15:00</lire:name> <lire:value col="download_count" missing-cases="0">0</lire:value> <lire:value col="download_ratio" missing-cases="0" value="0">0.0</lire:value> <lire:value col="user_count" missing-cases="0">0</lire:value> <lire:value col="user_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="13"> <lire:name col="timegroup:time_start" value="1043525700" range="900"> 15:15</lire:name> <lire:value col="download_count" missing-cases="0">2</lire:value> <lire:value col="download_ratio" missing-cases="0" value="2">4.2</lire:value> <lire:value col="user_count" missing-cases="0">2</lire:value> <lire:value col="user_ratio" missing-cases="0" value="2">20.0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>JPEG Files</lire:title> <lire:description><para>Applied filter in this section: selected files matching .*.jpg$</para> </lire:description> <lire:subreport type="top-files" superservice="test" schemas="test"> <lire:title>Downloads by File, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="file" class="categorical" type="filename" col-start="0" col-end="0" col-width="20" label="File" max-chars="20" avg-chars="18"/> <lire:column-info name="request_total" class="numerical" type="int" col-start="1" col-end="1" col-width="9" label="Downloads" max-chars="9" avg-chars="3"/> <lire:column-info name="request_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="38" missing-cases="0"> <lire:value col="request_total" missing-cases="0">38</lire:value> <lire:value col="request_ratio" missing-cases="0" value="38">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">10.5</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">10.5</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">10.5</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">10.5</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:value col="request_total" missing-cases="0">4</lire:value> <lire:value col="request_ratio" missing-cases="0" value="4">10.5</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">5.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">5.3</lire:value> </lire:entry> <lire:entry> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:value col="request_total" missing-cases="0">2</lire:value> <lire:value col="request_ratio" missing-cases="0" value="2">5.3</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="top-dirs" superservice="test" schemas="test-extended"> <lire:title>Downloads by Directory, Top 5</lire:title> <lire:table show="5"> <lire:table-info> <lire:column-info name="dirname" class="categorical" type="filename" col-start="0" col-end="0" col-width="9" label="Directory" max-chars="9" avg-chars="9"/> <lire:column-info name="bytes_total" class="numerical" type="bytes" col-start="1" col-end="1" col-width="16" label="Bytes Downloaded" max-chars="16" avg-chars="10"/> <lire:column-info name="bytes_ratio" class="numerical" type="bytes" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="6"/> </lire:table-info> <lire:group-summary nrecords="38" missing-cases="0"> <lire:value col="bytes_total" missing-cases="0" value="1015084">991.3k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="1015084">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="dirname">/pictures</lire:name> <lire:value col="bytes_total" missing-cases="0" value="1015084">991.3k</lire:value> <lire:value col="bytes_ratio" missing-cases="0" value="1015084">100.0</lire:value> </lire:entry> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Sessions</lire:title> <lire:subreport type="sessions-by-length" superservice="test" schemas="test-derived"> <lire:title>Sessions by Length</lire:title> <lire:table> <lire:table-info> <lire:column-info name="rangegroup:session_length" class="categorical" type="duration" col-start="0" col-end="0" col-width="9" label="Length" max-chars="9" avg-chars="9"/> <lire:column-info name="sessions_count" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="2"/> <lire:column-info name="sessions_ratio" class="numerical" type="int" col-start="2" col-end="2" col-width="7" label="% Total" max-chars="7" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="10" missing-cases="0"> <lire:value col="sessions_count" missing-cases="0">10</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="10">100.0</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="rangegroup:session_length" value="0" range="60">[0s-1m></lire:name> <lire:value col="sessions_count" missing-cases="0">2</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="2">20.0</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="rangegroup:session_length" value="60" range="60">[1m-2m></lire:name> <lire:value col="sessions_count" missing-cases="0">2</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="2">20.0</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="rangegroup:session_length" value="120" range="60">[2m-3m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="rangegroup:session_length" value="180" range="60">[3m-4m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="rangegroup:session_length" value="240" range="60">[4m-5m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="5"> <lire:name col="rangegroup:session_length" value="300" range="60">[5m-6m></lire:name> <lire:value col="sessions_count" missing-cases="0">2</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="2">20.0</lire:value> </lire:entry> <lire:entry row-idx="6"> <lire:name col="rangegroup:session_length" value="360" range="60">[6m-7m></lire:name> <lire:value col="sessions_count" missing-cases="0">2</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="2">20.0</lire:value> </lire:entry> <lire:entry row-idx="7"> <lire:name col="rangegroup:session_length" value="420" range="60">[7m-8m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="8"> <lire:name col="rangegroup:session_length" value="480" range="60">[8m-9m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="9"> <lire:name col="rangegroup:session_length" value="540" range="60">[9m-10m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="10"> <lire:name col="rangegroup:session_length" value="600" range="60">[10m-11m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="11"> <lire:name col="rangegroup:session_length" value="660" range="60">[11m-12m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="12"> <lire:name col="rangegroup:session_length" value="720" range="60">[12m-13m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="13"> <lire:name col="rangegroup:session_length" value="780" range="60">[13m-14m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="14"> <lire:name col="rangegroup:session_length" value="840" range="60">[14m-15m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="15"> <lire:name col="rangegroup:session_length" value="900" range="60">[15m-16m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="16"> <lire:name col="rangegroup:session_length" value="960" range="60">[16m-17m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="17"> <lire:name col="rangegroup:session_length" value="1020" range="60">[17m-18m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="18"> <lire:name col="rangegroup:session_length" value="1080" range="60">[18m-19m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="19"> <lire:name col="rangegroup:session_length" value="1140" range="60">[19m-20m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="20"> <lire:name col="rangegroup:session_length" value="1200" range="60">[20m-21m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="21"> <lire:name col="rangegroup:session_length" value="1260" range="60">[21m-22m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="22"> <lire:name col="rangegroup:session_length" value="1320" range="60">[22m-23m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="23"> <lire:name col="rangegroup:session_length" value="1380" range="60">[23m-24m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="24"> <lire:name col="rangegroup:session_length" value="1440" range="60">[24m-25m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="25"> <lire:name col="rangegroup:session_length" value="1500" range="60">[25m-26m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="26"> <lire:name col="rangegroup:session_length" value="1560" range="60">[26m-27m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="27"> <lire:name col="rangegroup:session_length" value="1620" range="60">[27m-28m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="28"> <lire:name col="rangegroup:session_length" value="1680" range="60">[28m-29m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="29"> <lire:name col="rangegroup:session_length" value="1740" range="60">[29m-30m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="30"> <lire:name col="rangegroup:session_length" value="1800" range="60">[30m-31m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="31"> <lire:name col="rangegroup:session_length" value="1860" range="60">[31m-32m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="32"> <lire:name col="rangegroup:session_length" value="1920" range="60">[32m-33m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="33"> <lire:name col="rangegroup:session_length" value="1980" range="60">[33m-34m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="34"> <lire:name col="rangegroup:session_length" value="2040" range="60">[34m-35m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="35"> <lire:name col="rangegroup:session_length" value="2100" range="60">[35m-36m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="36"> <lire:name col="rangegroup:session_length" value="2160" range="60">[36m-37m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="37"> <lire:name col="rangegroup:session_length" value="2220" range="60">[37m-38m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="38"> <lire:name col="rangegroup:session_length" value="2280" range="60">[38m-39m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="39"> <lire:name col="rangegroup:session_length" value="2340" range="60">[39m-40m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="40"> <lire:name col="rangegroup:session_length" value="2400" range="60">[40m-41m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="41"> <lire:name col="rangegroup:session_length" value="2460" range="60">[41m-42m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="42"> <lire:name col="rangegroup:session_length" value="2520" range="60">[42m-43m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="43"> <lire:name col="rangegroup:session_length" value="2580" range="60">[43m-44m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="44"> <lire:name col="rangegroup:session_length" value="2640" range="60">[44m-45m></lire:name> <lire:value col="sessions_count" missing-cases="0">0</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="0">0.0</lire:value> </lire:entry> <lire:entry row-idx="45"> <lire:name col="rangegroup:session_length" value="2700" range="60">[45m-46m></lire:name> <lire:value col="sessions_count" missing-cases="0">2</lire:value> <lire:value col="sessions_ratio" missing-cases="0" value="2">20.0</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="sessions-by-user_class" superservice="test" schemas="test-derived"> <lire:title>Sessions by User Class</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user_class" class="categorical" type="string" col-start="0" col-end="0" col-width="10" label="user_class" max-chars="10" avg-chars="10"/> <lire:column-info name="sessions_total" class="numerical" type="int" col-start="1" col-end="1" col-width="8" label="Sessions" max-chars="8" avg-chars="5"/> </lire:table-info> <lire:group-summary nrecords="10" missing-cases="10"> <lire:value col="sessions_total" missing-cases="0">10</lire:value> </lire:group-summary> </lire:table> </lire:subreport> </lire:section> <lire:section> <lire:title>Download Reports</lire:title> <lire:subreport type="avg-file_size-by-timeslot" superservice="test" schemas="test"> <lire:title>Average File Size By 1h Timeslot</lire:title> <lire:table> <lire:table-info> <lire:column-info name="timeslot:time_start" class="categorical" type="timestamp" col-start="0" col-end="0" col-width="6" label="Length" max-chars="6" avg-chars="6"/> <lire:column-info name="avg_file_size" class="numerical" type="bytes" col-start="1" col-end="1" col-width="13" label="Avg File Size" max-chars="13" avg-chars="4"/> </lire:table-info> <lire:group-summary nrecords="48" missing-cases="0"> <lire:value col="avg_file_size" missing-cases="0" total="18075990" n="48" value="376583.12">367.8k</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="timeslot:time_start" value="2-0" range="1">00:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="1"> <lire:name col="timeslot:time_start" value="2-1" range="1">01:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="2"> <lire:name col="timeslot:time_start" value="2-2" range="1">02:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="3"> <lire:name col="timeslot:time_start" value="2-3" range="1">03:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="4"> <lire:name col="timeslot:time_start" value="2-4" range="1">04:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="5"> <lire:name col="timeslot:time_start" value="2-5" range="1">05:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="6"> <lire:name col="timeslot:time_start" value="2-6" range="1">06:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="7"> <lire:name col="timeslot:time_start" value="2-7" range="1">07:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="8"> <lire:name col="timeslot:time_start" value="2-8" range="1">08:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="9"> <lire:name col="timeslot:time_start" value="2-9" range="1">09:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="10"> <lire:name col="timeslot:time_start" value="2-10" range="1">10:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="11"> <lire:name col="timeslot:time_start" value="2-11" range="1">11:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="12"> <lire:name col="timeslot:time_start" value="2-12" range="1">12:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="13426988" n="46" value="291891.04">285.0k</lire:value> </lire:entry> <lire:entry row-idx="13"> <lire:name col="timeslot:time_start" value="2-13" range="1">13:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="14"> <lire:name col="timeslot:time_start" value="2-14" range="1">14:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="15"> <lire:name col="timeslot:time_start" value="2-15" range="1">15:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="4649002" n="2" value="2324501.00">2.2M</lire:value> </lire:entry> <lire:entry row-idx="16"> <lire:name col="timeslot:time_start" value="2-16" range="1">16:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="17"> <lire:name col="timeslot:time_start" value="2-17" range="1">17:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="18"> <lire:name col="timeslot:time_start" value="2-18" range="1">18:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="19"> <lire:name col="timeslot:time_start" value="2-19" range="1">19:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="20"> <lire:name col="timeslot:time_start" value="2-20" range="1">20:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="21"> <lire:name col="timeslot:time_start" value="2-21" range="1">21:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="22"> <lire:name col="timeslot:time_start" value="2-22" range="1">22:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> <lire:entry row-idx="23"> <lire:name col="timeslot:time_start" value="2-23" range="1">23:00</lire:name> <lire:value col="avg_file_size" missing-cases="0" total="0" n="0">NaN</lire:value> </lire:entry> </lire:table> </lire:subreport> <lire:subreport type="user_downloads-report" superservice="test" schemas="test"> <lire:title>User's Downloads Report</lire:title> <lire:table> <lire:table-info> <lire:column-info name="user" class="categorical" type="string" col-start="0" col-end="3" col-width="2" label="Username" max-chars="8" avg-chars="7"/> <lire:column-info name="first_file" class="numerical" type="filename" col-start="4" col-end="4" col-width="20" label="First File" max-chars="20" avg-chars="18"/> <lire:column-info name="last_file" class="numerical" type="filename" col-start="5" col-end="5" col-width="20" label="Last File" max-chars="20" avg-chars="18"/> <lire:column-info name="min_file_size" class="numerical" type="bytes" col-start="6" col-end="6" col-width="8" label="Smallest" max-chars="8" avg-chars="6"/> <lire:column-info name="max_file_size" class="numerical" type="bytes" col-start="7" col-end="7" col-width="7" label="Largest" max-chars="7" avg-chars="5"/> <lire:group-info name="records:3" row-idx="1"> <lire:column-info name="time_start" class="categorical" type="timestamp" col-start="1" col-end="1" col-width="19" label="Start Time" max-chars="19" avg-chars="19"/> <lire:column-info name="file" class="categorical" type="filename" col-start="2" col-end="2" col-width="20" label="File" max-chars="20" avg-chars="20"/> <lire:column-info name="file_size" class="categorical" type="bytes" col-start="3" col-end="3" col-width="6" label="Size" max-chars="6" avg-chars="5"/> </lire:group-info> </lire:table-info> <lire:group-summary nrecords="48" missing-cases="0"> <lire:value col="first_file" missing-cases="0" total="1043514000">/pictures/000001.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="13245">12.9k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> </lire:group-summary> <lire:entry row-idx="0"> <lire:name col="user">bjoy</lire:name> <lire:value col="first_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043526410">/movies/001145.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="2" missing-cases="0" row-idx="0"> </lire:group-summary> <lire:entry row-idx="1"> <lire:name col="time_start" value="1043526410">2003-01-25 15:26:50</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="2"> <lire:name col="time_start" value="1043526410">2003-01-25 15:26:50</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="3"> <lire:name col="user">flacoste</lire:name> <lire:value col="first_file" missing-cases="0" total="1043514300">/movies/000002.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043515075">/movies/000003.mpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="232450">227.0k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="1324500">1.3M</lire:value> <lire:group> <lire:group-summary nrecords="4" missing-cases="0" row-idx="3"> </lire:group-summary> <lire:entry row-idx="4"> <lire:name col="time_start" value="1043514300">2003-01-25 12:05:00</lire:name> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:name col="file_size" value="1324500">1.3M</lire:name> </lire:entry> <lire:entry row-idx="5"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:name col="file_size" value="232450">227.0k</lire:name> </lire:entry> <lire:entry row-idx="6"> <lire:name col="time_start" value="1043514300">2003-01-25 12:05:00</lire:name> <lire:name col="file">/movies/000002.mpg</lire:name> <lire:name col="file_size" value="1324500">1.3M</lire:name> </lire:entry> <lire:entry row-idx="7"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/movies/000003.mpg</lire:name> <lire:name col="file_size" value="232450">227.0k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="8"> <lire:name col="user">francis</lire:name> <lire:value col="first_file" missing-cases="0" total="1043514000">/pictures/000001.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043515075">/pictures/000019.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="13245">12.9k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="26" missing-cases="0" row-idx="8"> </lire:group-summary> <lire:entry row-idx="9"> <lire:name col="time_start" value="1043514000">2003-01-25 12:00:00</lire:name> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:name col="file_size" value="13245">12.9k</lire:name> </lire:entry> <lire:entry row-idx="10"> <lire:name col="time_start" value="1043514305">2003-01-25 12:05:05</lire:name> <lire:name col="file">/pictures/001001.jpg</lire:name> <lire:name col="file_size" value="16432">16.0k</lire:name> </lire:entry> <lire:entry row-idx="11"> <lire:name col="time_start" value="1043514400">2003-01-25 12:06:40</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="12"> <lire:name col="time_start" value="1043515000">2003-01-25 12:16:40</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="13"> <lire:name col="time_start" value="1043515006">2003-01-25 12:16:46</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="14"> <lire:name col="time_start" value="1043515010">2003-01-25 12:16:50</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="15"> <lire:name col="time_start" value="1043515015">2003-01-25 12:16:55</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="16"> <lire:name col="time_start" value="1043515020">2003-01-25 12:17:00</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="17"> <lire:name col="time_start" value="1043515027">2003-01-25 12:17:07</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="18"> <lire:name col="time_start" value="1043515038">2003-01-25 12:17:18</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="19"> <lire:name col="time_start" value="1043515050">2003-01-25 12:17:30</lire:name> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="20"> <lire:name col="time_start" value="1043515057">2003-01-25 12:17:37</lire:name> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:name col="file_size" value="56345">55.0k</lire:name> </lire:entry> <lire:entry row-idx="21"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/pictures/000019.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="22"> <lire:name col="time_start" value="1043514000">2003-01-25 12:00:00</lire:name> <lire:name col="file">/pictures/000001.jpg</lire:name> <lire:name col="file_size" value="13245">12.9k</lire:name> </lire:entry> <lire:entry row-idx="23"> <lire:name col="time_start" value="1043514305">2003-01-25 12:05:05</lire:name> <lire:name col="file">/pictures/001001.jpg</lire:name> <lire:name col="file_size" value="16432">16.0k</lire:name> </lire:entry> <lire:entry row-idx="24"> <lire:name col="time_start" value="1043514400">2003-01-25 12:06:40</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="25"> <lire:name col="time_start" value="1043515000">2003-01-25 12:16:40</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="26"> <lire:name col="time_start" value="1043515006">2003-01-25 12:16:46</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="27"> <lire:name col="time_start" value="1043515010">2003-01-25 12:16:50</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="28"> <lire:name col="time_start" value="1043515015">2003-01-25 12:16:55</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="29"> <lire:name col="time_start" value="1043515020">2003-01-25 12:17:00</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="30"> <lire:name col="time_start" value="1043515027">2003-01-25 12:17:07</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="31"> <lire:name col="time_start" value="1043515038">2003-01-25 12:17:18</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="32"> <lire:name col="time_start" value="1043515050">2003-01-25 12:17:30</lire:name> <lire:name col="file">/pictures/000017.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="33"> <lire:name col="time_start" value="1043515057">2003-01-25 12:17:37</lire:name> <lire:name col="file">/pictures/000018.jpg</lire:name> <lire:name col="file_size" value="56345">55.0k</lire:name> </lire:entry> <lire:entry row-idx="34"> <lire:name col="time_start" value="1043515075">2003-01-25 12:17:55</lire:name> <lire:name col="file">/pictures/000019.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="35"> <lire:name col="user">joostvb</lire:name> <lire:value col="first_file" missing-cases="0" total="1043516010">/pictures/000012.jpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043516037">/pictures/000016.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:group> <lire:group-summary nrecords="10" missing-cases="0" row-idx="35"> </lire:group-summary> <lire:entry row-idx="36"> <lire:name col="time_start" value="1043516010">2003-01-25 12:33:30</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="37"> <lire:name col="time_start" value="1043516015">2003-01-25 12:33:35</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="38"> <lire:name col="time_start" value="1043516020">2003-01-25 12:33:40</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="39"> <lire:name col="time_start" value="1043516027">2003-01-25 12:33:47</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="40"> <lire:name col="time_start" value="1043516037">2003-01-25 12:33:57</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="41"> <lire:name col="time_start" value="1043516010">2003-01-25 12:33:30</lire:name> <lire:name col="file">/pictures/000012.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="42"> <lire:name col="time_start" value="1043516015">2003-01-25 12:33:35</lire:name> <lire:name col="file">/pictures/000013.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="43"> <lire:name col="time_start" value="1043516020">2003-01-25 12:33:40</lire:name> <lire:name col="file">/pictures/000014.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="44"> <lire:name col="time_start" value="1043516027">2003-01-25 12:33:47</lire:name> <lire:name col="file">/pictures/000015.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="45"> <lire:name col="time_start" value="1043516037">2003-01-25 12:33:57</lire:name> <lire:name col="file">/pictures/000016.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> <lire:entry row-idx="46"> <lire:name col="user">wdankers</lire:name> <lire:value col="first_file" missing-cases="0" total="1043516400">/movies/001145.mpg</lire:value> <lire:value col="last_file" missing-cases="0" total="1043516705">/pictures/000011.jpg</lire:value> <lire:value col="min_file_size" missing-cases="0" value="26345">25.7k</lire:value> <lire:value col="max_file_size" missing-cases="0" value="2324501">2.2M</lire:value> <lire:group> <lire:group-summary nrecords="6" missing-cases="0" row-idx="46"> </lire:group-summary> <lire:entry row-idx="47"> <lire:name col="time_start" value="1043516400">2003-01-25 12:40:00</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="48"> <lire:name col="time_start" value="1043516701">2003-01-25 12:45:01</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="49"> <lire:name col="time_start" value="1043516705">2003-01-25 12:45:05</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="50"> <lire:name col="time_start" value="1043516400">2003-01-25 12:40:00</lire:name> <lire:name col="file">/movies/001145.mpg</lire:name> <lire:name col="file_size" value="2324501">2.2M</lire:name> </lire:entry> <lire:entry row-idx="51"> <lire:name col="time_start" value="1043516701">2003-01-25 12:45:01</lire:name> <lire:name col="file">/pictures/000010.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> <lire:entry row-idx="52"> <lire:name col="time_start" value="1043516705">2003-01-25 12:45:05</lire:name> <lire:name col="file">/pictures/000011.jpg</lire:name> <lire:name col="file_size" value="26345">25.7k</lire:name> </lire:entry> </lire:group> </lire:entry> </lire:table> </lire:subreport> </lire:section> </lire:report> ������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/i18n.pm��������������������������������������������������������������������0000644�0001750�0001750�00000000663�10460672601�013173� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::i18n; use base 'Test::Unit::TestSuite'; sub name { 'Unit Tests Related To I18N' } sub include_tests { return qw/tests::config tests::I18NTest tests::DlfSchemaTest tests::ReportOperatorTest tests::FieldTest tests::GroupFieldTest tests::ReportSectionTest tests::ParamTest tests::ReportParserAsciiWriterTest tests::XMLSpecContainerTest /; } 1; �����������������������������������������������������������������������������lire-2.1.1/all/lib/tests/ParamTest.pm���������������������������������������������������������������0000644�0001750�0001750�00000004141�10460672577�014323� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::ParamTest; use strict; use Lire::Param; use base qw/Lire::Test::TestCase tests::TestStoreFixture/; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); $self->init_i18n(); return $self; } sub set_up { my $self = shift->SUPER::set_up(); $self->set_up_locale(); $self->set_up_test_schema(); my $param = new Lire::Param( 'i18n_domain' => 'lire-test', 'name' => 'whatever', 'type' => 'string', 'description' => '<para>JPEG Files</para>' ); $self->{'param'} = $param; return $self; } sub tear_down { my $self = shift->SUPER::tear_down(); $self->tear_down_locale(); return $self; } sub test_description_i18n { my $self = $_[0]; my $param = $self->{'param'}; $self->assert_str_equals( '<para>JPEG Files</para>', $param->description() ); $self->set_locale( 'fr_CA.iso8859-1' ); $self->assert_str_equals( '<para>Fichiers JPEG</para>', $param->description() ); } sub test_as_type_spec { my $self = $_[0]; my $param = $self->{'param'}; $param->{'default'} = 'A file'; my $spec = $param->as_type_spec(); $self->assert_isa( 'Lire::Config::StringSpec', $spec ); $self->assert_str_equals( 'whatever', $spec->name() ); $self->assert_str_equals( 'whatever', $spec->summary() ); $self->assert_str_equals( '<para>JPEG Files</para>', $spec->description() ); $self->assert_str_equals( 'lire-test', $spec->{'i18n_domain'} ); $self->assert_isa( 'Lire::Config::Scalar', $spec->default() ); $self->assert_str_equals( 'A file', $spec->default()->as_value() ); $param->{'default'} = undef; $param->{'type'} = 'int'; $self->assert_isa( 'Lire::Config::IntegerSpec', $param->as_type_spec() ); $param->{'type'} = 'filename'; $self->assert_isa( 'Lire::Config::FileSpec', $param->as_type_spec() ); $param->{'type'} = 'bool'; $self->assert_isa( 'Lire::Config::BooleanSpec', $param->as_type_spec() ); } 1; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/SQLExtRegistryTest.pm������������������������������������������������������0000644�0001750�0001750�00000002523�10460672577�016136� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::SQLExtRegistryTest; use strict; use base qw/Lire::Test::TestCase tests::TestStoreFixture/; use Lire::SQLExt::Registry; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); $self; } sub set_up { my $self = shift->SUPER::set_up(); $self->set_up_test_store(); } sub tear_down { my $self = shift->SUPER::tear_down(); $self->tear_down_test_store(); } sub mytestfunc { return 'mytestfunc'; } sub test_register_aggregates { my $self = $_[0]; local @Lire::SQLExt::Registry::EXT_AGGREGATES = ( [ 'myaggregate', 0, 'myaggregate' ] ); my $dbh = $self->{'store'}->_dbh(); Lire::SQLExt::Registry->register_aggregates( $dbh ); my $res = $dbh->selectrow_arrayref( "SELECT myaggregate() FROM dlf_test"); $self->assert_deep_equals( [ 260 ], $res ); } sub test_register_functions { my $self = $_[0]; local @Lire::SQLExt::Registry::EXT_FUNCTIONS = ( [ 'mytestfunc', 0, \&mytestfunc ] ); my $dbh = $self->{'store'}->_dbh(); Lire::SQLExt::Registry->register_functions( $dbh ); my $res = $dbh->selectrow_arrayref( "SELECT mytestfunc()" ); $self->assert_deep_equals( [ 'mytestfunc' ], $res ); } package myaggregate; sub new { return bless {}, shift; } sub step { return; } sub finalize { return 260; } 1; �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/UIDirectoryWidgetTest.pm���������������������������������������������������0000644�0001750�0001750�00000004276�10460672601�016626� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::UIDirectoryWidgetTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::Config::TypeSpec; use Lire::Test::CursesUIDriver; use Curses::UI; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'driver'} = new Lire::Test::CursesUIDriver(); $self->{'driver'}->setup_curses_ui(); $self->{'ui'} = new Curses::UI(); $self->{'driver'}->set_curses_ui( $self->{'ui'} ); $self->{'window'} = $self->{'ui'}->add( 'window', 'Window' ); my $spec = new Lire::Config::ConfigSpec(); $spec->add( new Lire::Config::DirectorySpec( 'name' => 'dir_param' ) ); $self->{'dir_param'} = $spec->get( 'dir_param' )->instance( 'value' => '/etc'); $self->{'spec'} = $spec; return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->{'driver'}->teardown_curses_ui(); return; } sub test_new { my $self = $_[0]; my $widget = $self->{'window'}->add( 'dir_widget', 'Lire::UI::DirectoryWidget', 'value' => $self->{'dir_param'} ); $self->assert_isa( 'Lire::UI::FileWidget', $widget ); $self->assert_isa( 'Lire::UI::DirectoryWidget', $widget ); } sub test_browse_dialog { my $self = $_[0]; my $dlg = '< undef >'; my $directory = $self->{'dir_param'}->get(); $self->{'driver'}->add_event_loop_handler( sub { $dlg = $_[1]; $self->assert_str_equals( $directory, $dlg->{'-path'} ); $dlg->getobj('pathvalue')->text( '/dev' ); $dlg->getobj('buttons')->{'-selected'} = 0; } ); my $widget = $self->{'window'}->add( 'test_widget','Lire::UI::DirectoryWidget', 'value' => $self->{'dir_param'} ); my $dir = $widget->browse_dialog(); $self->assert_isa('Curses::UI::Dialog::Dirbrowser', $dlg ); $self->assert_str_equals( '/dev', $dir ); $self->{'driver'}->add_event_loop_handler( sub { $dlg = $_[1]; $dlg->getobj('pathvalue')->text( '/sbin' ); $dlg->getobj('buttons')->{'-selected'} = 1; } ); $self->assert_null( $widget->browse_dialog(), 'expected undef from browse_dialog()' ); } 1; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/LrTimeslotTest.pm����������������������������������������������������������0000644�0001750�0001750�00000012001�10460672577�015353� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::LrTimeslotTest; use strict; use base qw/Lire::Test::TestCase/; use Lire::SQLExt::LrTimeslot; use POSIX qw/tzset/; sub test_lr_timeslot { my $self = $_[0]; my @tests = ( [ '2003-10-13 14:12:03 EDT', 'EST5EDT', 1066068723, 1, 's', 3 ], [ '2003-10-13 14:12:03 EDT', 'EST5EDT', 1066068723, 1, 'm', 12 ], [ '2003-10-13 00:00 EDT', 'EST5EDT', 1066017600, 1, 'h', 0 ], [ '2003-10-13 14:00 EDT', 'EST5EDT', 1066068000, 1, 'h', 14 ], [ '2003-10-13 14:12 EDT', 'EST5EDT', 1066068720, 1, 'h', 14 ], [ '2003-10-13 23:12 EDT', 'EST5EDT', 1066101120, 1, 'h', 23 ], [ '2003-10-13 00:00 EDT', 'EST5EDT', 1066017600, 4, 'h', 0 ], [ '2003-10-13 14:00 EDT', 'EST5EDT', 1066068000, 4, 'h', 12 ], [ '2003-10-13 23:12 EDT', 'EST5EDT', 1066101120, 4, 'h', 20 ], [ '2003-10-13 23:12 EDT', 'EST5EDT', 1066101120, 5, 'h', 20 ], [ '2003-10-13 00:00 EDT', 'EST5EDT', 1066017600, 1, 'd', 1 ], [ '2003-10-13 00:00 UTC', 'UTC', 1066003200, 1, 'd', 1 ], [ '2003-10-12 01:00 EDT', 'EST5EDT', 1065934800, 1, 'd', 0 ], [ '2003-10-12 01:00 UTC', 'UTC', 1065920400, 1, 'd', 0 ], [ '2003-10-13 00:00 EDT', 'EST5EDT', 1066017600, 2, 'd', 0 ], [ '2003-10-13 00:00 UTC', 'UTC', 1066003200, 2, 'd', 0 ], [ '2003-01-01 00:00 EDT', 'EST5EDT', 1041397200, 1, 'M', 0 ], [ '2003-01-01 00:00 UTC', 'UTC', 1041379200, 1, 'M', 0 ], [ '2003-12-31 00:00 EDT', 'EST5EDT', 1072846800, 1, 'M', 11 ], [ '2003-12-31 00:00 UTC', 'UTC', 1072828800, 1, 'M', 11 ], [ '2003-01-01 00:00 EDT', 'EST5EDT', 1041397200, 3, 'M', 0 ], [ '2003-01-01 00:00 UTC', 'UTC', 1041379200, 3, 'M', 0 ], [ '2003-12-31 00:00 EDT', 'EST5EDT', 1072846800, 3, 'M', 9 ], [ '2003-12-31 00:00 UTC', 'UTC', 1072828800, 3, 'M', 9 ], ); $self->assert_null( Lire::SQLExt::LrTimeslot::lr_timeslot( undef, 1, 'h' ), "lr_timeslot( undef ) should return undef" ); $self->assert_null( Lire::SQLExt::LrTimeslot::lr_timeslot( time, 1, 'x' ), "lr_timeslot( time(), 1, 'x' ) should return undef" ); $self->assert_null( Lire::SQLExt::LrTimeslot::lr_timeslot( time, undef, 'h' ), "lr_timeslot( time(), undef, 'h' ) should return undef" ); my $old_tz = $ENV{'TZ'}; foreach my $t ( @tests ) { my ( $date, $tz, $epoch, $mult, $unit, $result ) = @$t; $ENV{'TZ'} = $tz; tzset(); my $r = Lire::SQLExt::LrTimeslot::lr_timeslot( $epoch, $mult, $unit ); $ENV{'TZ'} = $old_tz || ''; tzset(); $self->assert_not_null( $r, "lr_timeslot( '$date', $mult, $unit ) returned undef" ); $self->assert_equals( $result, $r, "lr_timeslot( '$date', $mult, $unit ) returned $r, expected $result" ); } } sub test_lr_timeslot_week { my $self = $_[0]; my @tests = ( [ '2003-01-01 00:15 CET', 'CET', 'ISO', 1, 1041376500, 1 ], [ '2003-01-01 00:15 CET', 'CET', 'ISO', 4, 1041376500, 1 ], [ '2002-12-31 23:15 CET', 'CET', 'ISO', 1, 1041372900, 1 ], [ '2003-10-14 12:00 UTC', 'UTC', 'ISO', 1, 1066125600, 42 ], [ '2003-10-14 12:00 UTC', 'UTC', 'ISO', 4, 1066125600, 41 ], [ '2003-01-22 00:00 EST', 'EST', 'ISO', 4, 1043211600, 1 ], [ '2003-01-29 00:00 EST', 'EST', 'ISO', 4, 1043816400, 5 ], [ '2003-02-19 00:00 EST', 'EST', 'ISO', 4, 1045630800, 5 ], # Weeks start on sunday [ '2003-01-01 00:15 CET', 'CET', 'U', 1, 1041376500, 0 ], # Week 0 is grouped in Week 1 [ '2003-01-01 00:15 CET', 'CET', 'U', 4, 1041376500, 1 ], [ '2002-12-31 23:15 CET', 'CET', 'U', 1, 1041372900, 52 ], [ '2003-10-14 12:00 UTC', 'UTC', 'U', 1, 1066125600, 41 ], [ '2003-10-14 12:00 UTC', 'UTC', 'U', 4, 1066125600, 41 ], [ '2003-01-29 00:00 EST', 'EST', 'U', 4, 1043816400, 1 ], [ '2003-02-04 00:00 EST', 'EST', 'U', 4, 1044334800, 5 ], ); $self->assert_null( Lire::SQLExt::LrTimeslot::lr_timeslot_week( undef ), "lr_timeslot_week( undef ) should return undef" ); $self->assert_null( Lire::SQLExt::LrTimeslot::lr_timeslot_week( time(), undef ), "lr_timeslot_week( time(), undef ) should return undef" ); my $old_tz = $ENV{'TZ'}; foreach my $t ( @tests ) { my ( $date, $tz, $style, $mult, $epoch, $result ) = @$t; $ENV{'TZ'} = $tz; tzset(); $self->{'cfg'}{'lr_week_numbering'} = $style; $Lire::SQLExt::LrTimeslot::calc = undef; my $r = Lire::SQLExt::LrTimeslot::lr_timeslot_week( $epoch, $mult ); $ENV{'TZ'} = $old_tz || ''; tzset(); $self->assert_not_null( "lr_timeslot_week( '$date', $mult ) using $style returned undef" ); $self->assert_equals( $result, $r, "lr_timeslot_week( '$date', $mult ) using $style returned $r, expected $result" ); } } 1; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/TimeslotTest.pm������������������������������������������������������������0000644�0001750�0001750�00000011215�10460672600�015046� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::TimeslotTest; use strict; use base qw/Lire::Test::TestCase tests::TestStoreFixture/; use Lire::Timeslot; use Lire::ReportSpec; use Lire::Report::Group; use Lire::Report::TableInfo; use Lire::DlfQuery; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->set_up_test_schema(); $self->set_up_tz( 'UTC' ); $self->{'spec'} = new Lire::ReportSpec(); $self->{'spec'}->superservice( 'test' ); $self->{'spec'}->id( 'timeslot-test' ); foreach my $p ( qw/3M 1w 4w 1d 4h 15m 15s/ ) { $self->{ $p . '_timeslot'} = new Lire::Timeslot( 'report_spec' => $self->{'spec'}, 'unit' => $p, 'label' => 'Period', ); } return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub test_name { my $self = $_[0]; $self->assert_equals( 'timeslot:time_start', $self->{'1d_timeslot'}->name() ); } sub test_create_categorical_info { my $self = $_[0]; my $info = new Lire::Report::TableInfo(); $self->{'1d_timeslot'}->create_categorical_info( $info ); my @cols = $info->children(); $self->assert_equals( 1, scalar @cols ); my $col = $cols[0]; $self->assert_equals( 'categorical', $col->class() ); $self->assert_equals( 'timeslot:time_start', $col->name() ); $self->assert_equals( 'timestamp', $col->type() ); $self->assert_equals( 'Period', $col->label() ); } sub test_build_query { my $self = $_[0]; foreach my $t ( [ '3M', q{lr_timeslot("time-start",3,'M')} ], [ '1w', 'lr_timeslot_week("time-start",1)' ] ) { my $timeslot = $self->{ $t->[0] . '_timeslot' }; $timeslot->{'field'} = 'time-start'; my $e_query = new Lire::DlfQuery( 'test' ); $e_query->add_aggr_field( '_lr_nrecords', 'count(*)' ); $e_query->add_group_field( 'timeslot:time-start', $t->[1] ); $e_query->set_sort_spec( 'timeslot:time-start' ); my $query = new Lire::DlfQuery( 'test' ); $timeslot->build_query( $query ); $self->assert_deep_equals( $e_query, $query ); } } sub test_create_entry { my $self = $_[0]; my $info = new Lire::Report::TableInfo(); $self->{'1d_timeslot'}->create_categorical_info( $info ); foreach my $t ( [ '3M', 9, 'October', undef, 'M3', 3 ], [ '1w', 42, '-W42', 'ISO', 'W41', 1 ], [ '1w', 41, 'Week 41', 'U', 'W40', 1 ], [ '1w', 0, 'Week 00', 'U', 'W0', 1 ], [ '4w', 1, '-W01', 'ISO', 'W0', 4 ], [ '4w', 5, '-W05', 'ISO', 'W1', 4 ], [ '4w', 1, 'Week 01', 'U', 'W0', 4 ], [ '1d', 2, 'Tuesday', undef, 'D2', 1 ], [ '4h', 16, '16:00', undef, '2-4', 4 ], [ '15m', 7, '00:07', undef, '1-0', 15 ], [ '15m', 0, '00:00', undef, '1-0', 15 ], [ '15s', 9, '00:00:09', undef, '0-0', 15 ], [ '15s', 15, '00:00:15', undef, '0-1', 15 ], ) { my ( $period, $slot, $fmt_value, $style, $value, $mult ) = @$t; $self->{'cfg'}{'lr_week_numbering'} = $style if defined $style; my $timeslot = $self->{$period . '_timeslot'}; my $dlf = { 'timeslot:time_start' => $slot }; my $group = new Lire::Report::Group( bless( {}, 'Lire::Report::Entry'), $info ); my $entry = $timeslot->create_entry( $group, $dlf ); $self->assert_not_null( $entry, "create_entry() returned undef" ); my @data = $entry->data(); $self->assert_num_equals( 1, scalar @data ); $self->assert_str_equals( $fmt_value, $data[0]->{'content'} ); $self->assert_str_equals( $value, $data[0]->{'value'} ); $self->assert_num_equals( $mult, $data[0]->{'range'} ); } } sub test_create_entry_mc { my $self = $_[0]; my $timeslot = $self->{'3M_timeslot'}; my $info = new Lire::Report::TableInfo(); $timeslot->create_categorical_info( $info ); my $group = new Lire::Report::Group( bless( {}, 'Lire::Report::Entry'), $info ); my $entry = $timeslot->create_entry( $group, { 'timeslot:time-start' => undef, '_lr_nrecords' => 24 } ); $self->assert_null( $entry, "create_entry() should have returned undef" ); $self->assert_equals( 24, $group->missing_cases() ); } 1; �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/TestStoreFixture.pm��������������������������������������������������������0000644�0001750�0001750�00000005133�10460672600�015713� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::TestStoreFixture; use strict; use Cwd qw/realpath/; use File::Path qw/mkpath rmtree/; use File::Basename qw/dirname/; use POSIX qw/setlocale LC_MESSAGES/; use Locale::Messages qw/bindtextdomain bind_textdomain_codeset/; use Lire::Config::SpecParser; use Lire::Config::TypeSpec; use Lire::DlfStore; use Lire::Utils qw/tempdir/; # # Fixture which initialize for TestCase which requires the use # of test_store. # # It also makes available the test schemas. # # The test_store will be accessible through the 'store' attribute. # sub init { my $self = $_[0]; $self->{'testdir'} = realpath( dirname(__FILE__) ); $self->{'schemasdir'} = $self->{'testdir'} . "/schemas"; $self->{'store_tar'} = $self->{'testdir'} . "/data/test_store.tar"; return; } sub init_i18n { my $self = $_[0]; $self->{'localedir'} = tempdir( __PACKAGE__ . "XXXXXX", CLEANUP => 1 ); mkpath( [ $self->{'localedir'} . "/fr/LC_MESSAGES" ], 0, 0755 ); system( "cp $self->{'testdir'}/po/fr.mo $self->{'localedir'}/fr/LC_MESSAGES/lire-test.mo" ); return; } sub set_up_test_schema { my $self = $_[0]; $self->{'cfg'}{'lr_schemas_path'} = [ $self->{'schemasdir'}, "$self->{'testdir'}/../../schemas" ]; return; } sub set_up_test_store { my ( $self, $open ) = @_; $open = 1 unless defined $open; $self->set_up_test_schema(); $self->{'tmpdir'} = tempdir( __PACKAGE__ . "XXXXXX", CLEANUP => 1 ); system( "cd $self->{'tmpdir'}; tar xf $self->{'store_tar'}" ); die "tar failed: $?" if $?; # Lire::DlfStore::open calls Lire::Config->config_spec() $self->{'cfg'}{'_lr_config_spec'} = $self->lire_default_config_spec() unless ( $self->{'cfg'}{'_lr_config_spec'} && $self->{'cfg'}{'_lr_config_spec'}->has_component( 'streams_config' ) ); $self->{'store_path'} = "$self->{'tmpdir'}/test_store"; $self->{'store'} = Lire::DlfStore->open( $self->{'store_path'} ) if $open; return; } sub set_up_locale { my $self = $_[0]; $self->{'old_localedir'} = bindtextdomain( 'lire-test' ); bindtextdomain( 'lire-test', $self->{'localedir'} ); bind_textdomain_codeset( 'lire-test', 'iso-8859-1' ); return; } sub tear_down_locale { my $self = $_[0]; bindtextdomain( 'lire-test', $self->{'old_localedir'} ); return; } sub set_locale { my ( $self, $locale ) = @_; setlocale( LC_MESSAGES, $locale ); } sub tear_down_test_store { my $self = $_[0]; $self->{'store'}->close(); rmtree( $self->{'tmpdir'} ); return; } 1; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/DlfCategoriserTest.pm������������������������������������������������������0000644�0001750�0001750�00000016433�10460672600�016152� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::DlfCategoriserTest; use strict; use base qw/ Lire::Test::TestCase tests::TestStoreFixture /; use Lire::DlfCategoriser; use Lire::DlfAnalyserProcess; use Lire::PluginManager; use Time::Local; use Class::Inner; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); $self->{'config'} = { 'name' => 'value' }; $self->{'20040311_121201'} = timelocal( 1, 12, 12, 11, 2, 2004 ); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->set_up_test_schema(); $self->set_up_test_store(); $self->set_up_plugin_mgr(); push@{$self->{'cfg'}{'lr_schemas_path'}}, "$self->{'testdir'}/../../schemas"; return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->tear_down_test_store(); return; } sub test_analyse { my $self = $_[0]; my $categoriser = new Class::Inner( 'parent' => 'Lire::DlfCategoriser', 'methods' => { 'new' => sub { bless [], shift }, 'name' => sub { 'extended' }, 'src_schema' => sub { 'test' }, 'dst_schema' => sub { 'test-extended' }, 'initialise' => sub { push @{$_[0]}, [ 'initialise', @_ ] }, 'categorise' => sub { push @{$_[0]}, [ 'categorise', @_ ] }, 'finalise' => sub { push @{$_[0]}, [ 'finalise', @_]}, } ); my $process = $self->create_mock_process( $categoriser ); my $stream = $self->{'store'}->open_dlf_stream( 'test', 'w' ); $stream->clean(); $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} -86400, 'dlf_source' => 'a_source' } ); $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} - 3600, 'dlf_source' => 'my_source' } ); $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'}, 'dlf_source' => 'my_source' } ); $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} +3600, 'dlf_source' => 'my_source' } ); $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} +86400, 'dlf_source' => 'another_source' } ); $stream->close(); $process->run_analysis_job( $self->{'20040311_121201'} ); $self->assert_num_equals( 5, scalar @$categoriser ); $self->assert_str_equals( 'initialise', $categoriser->[0][0] ); $self->assert_str_equals( 'categorise', $categoriser->[1][0] ); $self->assert_num_equals( $self->{'20040311_121201'} -3600, $categoriser->[1][2]{'time_start'} ); $self->assert_num_equals( $self->{'20040311_121201'}, $categoriser->[2][2]{'time_start'} ); $self->assert_num_equals( $self->{'20040311_121201'} +3600, $categoriser->[3][2]{'time_start'} ); $self->assert_str_equals( 'finalise', $categoriser->[4][0] ); $self->assert_null( $process->{'errors'} ); $self->assert_num_equals( 3, scalar @{$process->{'dlf'}} ); $self->assert_num_equals( $self->{'20040311_121201'} -3600, $process->{'dlf'}[0]{'time_start'} ); $self->assert_num_equals( $self->{'20040311_121201'}, $process->{'dlf'}[1]{'time_start'} ); $self->assert_num_equals( $self->{'20040311_121201'} +3600, $process->{'dlf'}[2]{'time_start'} ); } sub test_analyse_derived { my $self = $_[0]; my $categoriser = new Class::Inner( 'parent' => 'Lire::DlfCategoriser', 'methods' => { 'new' => sub { bless [], shift }, 'name' => sub { 'derived' }, 'src_schema' => sub { 'test' }, 'dst_schema' => sub { 'test-derived' }, } ); my $process = $self->create_mock_process( $categoriser ); $self->assert_dies( qr/'derived' analyser doesn't declare to write to an ExtendedSchema: 'test-derived'/, sub { $categoriser->analyse( $process, {} ) } ); } sub test_analyse_failing_initialise { my $self = $_[0]; my $categoriser = new Class::Inner( 'parent' => 'Lire::DlfCategoriser', 'methods' => { 'new' => sub { bless [], shift }, 'name' => sub { 'failing_initialise' }, 'src_schema' => sub { 'test' }, 'dst_schema' => sub { 'test-extended' }, 'initialise' => sub { die "Failed\n" }, } ); my $process = $self->create_mock_process( $categoriser ); my $stream = $self->{'store'}->open_dlf_stream( 'test', 'w' ); $stream->clean(); $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'}} ); $stream->close(); $process->run_analysis_job( $self->{'20040311_121201'} ); $self->assert_null( $process->{'dlf'} ); $self->assert_deep_equals( [ "Error during initialise: Failed\n" ], $process->{'errors'} ); } sub test_analyse_failing_categorise { my $self = $_[0]; my $categoriser = new Class::Inner( 'parent' => 'Lire::DlfCategoriser', 'methods' => { 'new' => sub { bless [], shift }, 'name' => sub { 'failing_categorise' }, 'src_schema' => sub { 'test' }, 'dst_schema' => sub { 'test-extended' }, 'initialise' => sub {}, 'categorise' => sub { die "Failed\n" }, } ); my $process = $self->create_mock_process( $categoriser ); my $stream = $self->{'store'}->open_dlf_stream( 'test', 'w' ); $stream->clean(); $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} - 3600, 'dlf_source' => 'my_source' } ); $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} , 'dlf_source' => 'my_source' } ); $stream->close(); $process->run_analysis_job( $self->{'20040311_121201'} ); $self->assert_deep_equals( [ "Failed\n", "Failed\n", ], $process->{'errors'} ); $self->assert_null( $process->{'dlf'} ); } sub create_mock_process { my ($self, $categoriser) = @_; Lire::PluginManager->register_plugin( $categoriser ); return new Class::Inner( 'parent' => 'Lire::DlfAnalyserProcess', 'args' => [ $self->{'store'}, $categoriser->name(), $self->{'config'}, 'my_source' ], 'methods' => { 'error' => sub { $_[0]{'errors'} ||= []; push @{$_[0]{'errors'}}, $_[1] }, 'write_dlf' => sub { $_[0]{'dlf'} ||= []; push @{$_[0]{'dlf'}}, $_[1] } } ); } 1; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/ImportJobTest.pm�����������������������������������������������������������0000644�0001750�0001750�00000012752�10460672600�015162� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::ImportJobTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::ImportJob; use POSIX qw/strftime/; use Lire::I18N qw/set_fh_encoding/; use Lire::Utils qw/tempfile/; use Lire::PluginManager; use Lire::DlfStore; use Lire::DlfConverter; use Lire::Test::Mock; sub new { my $self = shift()->SUPER::new( @_ ); $self->{'spec'} = $self->lire_default_config_spec(); $self->{'www_plugin'} = new_proxy Lire::Test::Mock( 'Lire::DlfConverter' ); $self->{'www_plugin'}->set_result( 'name' => 'www' ); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'cfg'}{'_lr_config_spec'} = $self->{'spec'}; $self->set_up_plugin_mgr(); Lire::PluginManager->register_plugin( $self->{'www_plugin'} ); return; } sub tear_down { my $self = $_[0]; Lire::Test::Mock->reset_factories(); unlink $self->{'tmpfile'} if $self->{'tmpfile'}; $self->SUPER::tear_down(); return; } sub test_new { my $self = $_[0]; my %args = ( 'period' => "unique", 'pattern' => "/var/log/messages", 'converter' => "www", 'encoding' => 'ISO-8859-1', 'filter' => 'cat', 'name' => "test", ); my $job = new Lire::ImportJob( "test", %args, 'converter_config' => {} ); $self->assert_isa( 'Lire::ImportJob', $job ); foreach my $a ( keys %args ) { no strict 'refs'; $self->assert_str_equals( $args{$a}, $job->$a() ); } $self->assert_deep_equals( {}, $job->converter_config() ); } sub test_file { my $self = $_[0]; my $job = new Lire::ImportJob( "test" ); $self->assert( UNIVERSAL::isa( $job, "Lire::ImportJob"), "constructor didn't returned an instance of Lire::ImportJob" ); $job->pattern( '/var/log/messages%Y%m' ); my $file = $job->file; $self->assert_not_null( $file, "file() returned undef" ); $self->assert_equals( strftime( '/var/log/messages%Y%m', localtime ), $file ); } sub test_new_from_config { my $self = $_[0]; my $job = $self->{'spec'}->get( 'import_jobs' )->get( 'import_job' )->instance(); $job->get( 'name' )->set( 'aJob' ); $job->get( 'filter' )->set( '' ); $job->get( 'log_encoding' )->set( 'UTF-8' ); $job->get( 'log_file' )->set( 'a file' ); $job->get( 'period' )->set( 'hourly' ); $job->get( 'service' )->set_plugin( 'www' ); my $jobObject = $job->as_value(); $self->assert_isa( 'Lire::ImportJob', $jobObject ); $self->assert_str_equals( 'aJob', $jobObject->{'_name'} ); $self->assert_str_equals( 'UTF-8', $jobObject->{'_encoding'} ); $self->assert_str_equals( 'www', $jobObject->{'_converter'} ); $self->assert_str_equals( 'a file', $jobObject->{'_pattern'} ); $self->assert_str_equals( 'hourly', $jobObject->{'_period'} ); $self->assert_deep_equals( {}, $jobObject->{'_converter_config'} ); $self->assert_null( $jobObject->{'_filter'} ); } sub test_log_fh_filter { my $self = $_[0]; my ( $fh, $name ) = tempfile( "log-utf8XXXXXX" ); $self->{'tmpfile'} = $name; print $fh "Line 1\nLine 2\n"; close $fh; my $job = new Lire::ImportJob( 'test', 'converter' => 'line', 'pattern' => $name, 'filter' => 'grep "Line 1"' ); my $job_fh = $job->log_fh(); $self->assert_deep_equals( [ "Line 1\n" ], [ <$job_fh> ] ); $job->filter( 'cat | grep "Line"' ); $job_fh = $job->log_fh(); $self->assert_deep_equals( [ "Line 1\n", "Line 2\n" ], [ <$job_fh> ] ); } sub test_log_fh_encoding { my $self = $_[0]; my $unistr = "This an A with a bar: \x{0100}\n"; my ( $fh, $name ) = tempfile( "log-utf8XXXXXX" ); $self->{'tmpfile'} = $name; set_fh_encoding( $fh, 'utf8' ); print $fh $unistr; close $fh; my $job = new Lire::ImportJob( "test", converter => 'line', 'pattern' => $name, 'encoding' => 'utf8' ); my $job_fh = $job->log_fh(); my $string = <$job_fh>; $self->assert_str_equals( $unistr, $string ); } sub test_run { my $self = $_[0]; $self->set_up_plugin_mgr(); my $line = new_proxy Lire::Test::Mock( 'Lire::DlfConverter' ); $line->set_result('name' => 'line', 'schemas' => sub { ( 'test', 'test-extended' ) } ); Lire::PluginManager->register_plugin( $line ); my $job = new Lire::ImportJob( "test", converter => 'line', 'pattern' => "test.log" ); my $store = new Lire::Test::Mock( 'Lire::DlfStore', 'has_dlf_stream' => sub { $_[1] eq 'test' } ); Lire::Test::Mock->set_mock_factory( 'Lire::DlfConverterProcess', 'run_import_job' => '', 'job_id' => 'my_id', ); $job->run( $store ); my $process = Lire::Test::Mock->mock_instances( 'Lire::DlfConverterProcess' ); $self->assert_num_equals( 1, scalar @$process ); $self->assert_str_equals( $store, $process->[0]->dlf_store() ); $self->assert_num_equals( 1, $process->[0]->invocation_count( 'run_import_job' ) ); $self->assert_num_equals( 1, $store->invocation_count( 'run_analysers' ) ); $self->assert_deep_equals( [ $store, 'test', 'my_id' ], $store->get_invocation( 'run_analysers', 0 ) ); } 1; ����������������������lire-2.1.1/all/lib/tests/ReportEntryTest.pm���������������������������������������������������������0000644�0001750�0001750�00000010130�10460672577�015553� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::ReportEntryTest; use strict; use base qw/Lire::Test::TestCase/; use Lire::Report::Group; use Lire::Report::Entry; use Lire::Report::TableInfo; sub set_up { my $self = shift->SUPER::set_up(); $self->{'info'} = new Lire::Report::TableInfo(); $self->{'info'}->create_column_info( 'value', 'numerical', 'int' ); $self->{'info'}->create_group_info( 'group' ); $self->{'group'} = new Lire::Report::Group( bless( {}, 'Lire::Report::Entry' ), $self->{'info'} ); return $self; } sub tear_down { my $self = shift->SUPER::tear_down(); return $self; } sub test_new { my $self = $_[0]; my $group = $self->{'group'}; $self->assert_died( sub { new Lire::Report::Entry() }, qr/missing \'group\' parameter/ ); $self->assert_died( sub { new Lire::Report::Entry( {} ) }, qr/\'group\' parameter should be a 'Lire::Report::Group' instance, not 'HASH/ ); my $entry = new Lire::Report::Entry( $group ); $self->assert_not_null( $entry, 'new() returned undef' ); $self->assert( UNIVERSAL::isa( $entry, 'Lire::Report::Entry' ), "new() should return instance of Lire::Report::Entry: $entry" ); $self->assert_deep_equals( [], $entry->{'data'} ); $self->assert_equals( $group, $entry->{'group'} ); } sub test_add_value { my $self = $_[0]; my $entry = new Lire::Report::Entry( $self->{'group'} ); $entry->add_value( { 'content' => '10.0', 'value' => '10.0', 'n' => '5', 'total' => '50', 'missing_cases' => 10, } ); $self->assert_deep_equals( [ { 'content' => '10.0', 'value' => '10.0', 'n' => '5', 'total' => '50', 'type' => 'value', 'col_info' => $self->{'info'}->info_by_index(0), 'missing_cases' => 10, } ], $entry->{'data'} ); $self->assert_died( sub { $entry->add_value( {} ) }, qr/\'Data_1\' parameter should be a \'Lire::Report::ColumnInfo\' instance, not \'Lire::Report::GroupInfo/ ); my $entry2 = new Lire::Report::Entry( $self->{'group'} ); $entry2->add_value( { 'content' => '10.0' } ); $self->assert_deep_equals( [ { 'content' => '10.0', 'value' => '10.0', 'n' => undef, 'total' => undef, 'type' => 'value', 'col_info' => $self->{'info'}->info_by_index(0), 'missing_cases' => 0, } ], $entry2->{'data'} ); my $entry3 = new Lire::Report::Entry( $self->{'group'} ); $entry3->add_value( {} ); $self->assert_deep_equals( [ { 'content' => '', 'value' => '', 'n' => undef, 'total' => undef, 'type' => 'value', 'col_info' => $self->{'info'}->info_by_index(0), 'missing_cases' => 0, } ], $entry3->{'data'} ); } sub test_add_value_old_signature { my $self = $_[0]; my $entry = new Lire::Report::Entry( $self->{'group'} ); $entry->add_value( 'content' => 1 ); $self->assert_deep_equals( [ { 'content' => 1, 'value' => 1, 'n' => undef, 'total' => undef, 'type' => 'value', 'col_info' => $self->{'info'}->info_by_index(0), 'missing_cases' => 0, } ], $entry->{'data'} ); } 1; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/XMLSpecContainerTest.pm����������������������������������������������������0000644�0001750�0001750�00000016212�10460672601�016367� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::XMLSpecContainerTest; use strict; use base qw/ Lire::Test::TestCase tests::TestStoreFixture/; use Lire::Param; use Lire::XMLSpecContainer; use Lire::DlfSchema; use Lire::Test::Mock; use Lire::Utils qw/create_file tempdir /; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); $self->init_i18n(); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'tmpdir'} = tempdir( __PACKAGE__ . "XXXXXX", CLEANUP => 1 ); $self->set_up_locale(); $self->set_up_test_schema(); my $spec = new Lire::XMLSpecContainer(); $spec->superservice( 'test' ); $spec->param( 'bidon', new Lire::Param( 'name' => 'bidon', 'type' => 'int', 'default' => 5 ) ); $self->{'xmlspec'} = $spec; $Lire::DlfSchema::SCHEMA_CACHE{'test2'} = new Lire::DlfSchema( 'superservice' => 'test2', 'timestamp' => 'time' ); return $self; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->tear_down_locale(); delete $Lire::DlfSChema::SCHEMA_CACHE{'test2'}; return $self; } sub test_schemas { my $self = $_[0]; my $spec = $self->{'xmlspec'}; $self->assert_deep_equals( [ 'test' ], $spec->schemas() ); $spec->joined_schemas( [ 'test-extended' ] ); $self->assert_deep_equals( [ 'test', 'test-extended' ], $spec->schemas() ); } sub test_joined_schemas { my $self = $_[0]; my $spec = $self->{'xmlspec'}; $self->assert_deep_equals( [], $spec->joined_schemas() ); $self->assert_dies( qr/no schema 'test-extended2'/, sub { $spec->joined_schemas( [ 'test-extended2'] ) } ); $self->assert_dies( qr/cannot join 'test2' schema with 'test'/, sub { $spec->joined_schemas( [ 'test2' ] ) } ); my $joined = [ 'test-extended' ]; $spec->joined_schemas( $joined ); $self->assert_deep_equals( $joined, $spec->{'_joined_schemas'} ); $self->assert_str_not_equals( $joined, $spec->{'_joined_schemas'} ); } sub test_has_field { my $self = $_[0]; my $spec = $self->{'xmlspec'}; $self->assert( $spec->has_field( 'connection_id' ) ); $self->assert( ! $spec->has_field( 'dirname' ) ); $spec->{'_joined_schemas'} = [ 'test-extended' ]; $self->assert( $spec->has_field( 'connection_id' ) ); $self->assert( $spec->has_field( 'dirname' ) ); } sub test_field { my $self = $_[0]; my $test = Lire::DlfSchema::load_schema( 'test' ); my $ext = Lire::DlfSchema::load_schema( 'test-extended' ); my $spec = $self->{'xmlspec'}; $self->assert_dies( qr/no field 'dirname' in this specification's schemas: test/, sub { $spec->field( 'dirname' ) } ); $self->assert_str_equals( $test->field( 'connection_id' ), $spec->field( 'connection_id' ) ); $spec->{'_joined_schemas'} = [ 'test-extended' ]; $self->assert_dies( qr/no field 'session_length' in this specification's schemas: test, test-extended/, sub { $spec->field( 'session_length' ) } ); $self->assert_str_equals( $test->field( 'connection_id' ), $spec->field( 'connection_id' ) ); $self->assert_str_equals( $ext->field( 'dirname' ), $spec->field( 'dirname' ) ); } sub test_resolve_param_ref { my $self = $_[0]; $self->assert_null( $self->{'xmlspec'}->resolve_param_ref(), 'expected undef' ); $self->assert_num_equals( 4, $self->{'xmlspec'}->resolve_param_ref( 4 )); $self->assert_num_equals( 5, $self->{'xmlspec'}->resolve_param_ref('$bidon' )); $self->assert_dies( qr/no such parameter: 'wawa'/, sub {$self->{'xmlspec'}->resolve_param_ref('$wawa')}); } sub test_title_i18n { my $self = $_[0]; my $spec = $self->{'xmlspec'}; $spec->{'title'} = 'JPEG Files'; $self->assert_str_equals( 'JPEG Files', $spec->title() ); $self->set_locale( 'fr_CA.iso8859-1' ); $self->assert_str_equals( 'Fichiers JPEG', $spec->title() ); } sub test_description_i18n { my $self = $_[0]; my $spec = $self->{'xmlspec'}; $spec->{'description'} = '<para>JPEG Files</para>'; $self->assert_str_equals( '<para>JPEG Files</para>', $spec->description() ); $self->set_locale( 'fr_CA.iso8859-1' ); $self->assert_str_equals( '<para>Fichiers JPEG</para>', $spec->description() ); } sub test_display_title_i18n { my $self = $_[0]; my $spec = $self->{'xmlspec'}; $spec->{'display_title'} = 'Downloads by File, Top $files_to_show'; $self->assert_str_equals( 'Downloads by File, Top $files_to_show', $spec->display_title() ); $self->set_locale( 'fr_CA.iso8859-1' ); $self->assert_str_equals( 'Transferts par fichiers, les $files_to_show les plus transfrs', $spec->display_title() ); } sub test_display_description_i18n { my $self = $_[0]; my $spec = $self->{'xmlspec'}; $spec->{'display_description'} = 'Downloads by File, Top $files_to_show'; $self->assert_str_equals( 'Downloads by File, Top $files_to_show', $spec->display_description() ); $self->set_locale( 'fr_CA.iso8859-1' ); $self->assert_str_equals( 'Transferts par fichiers, les $files_to_show les plus transfrs', $spec->display_description() ); } sub test_file_from_id { my $self = $_[0]; my $mock = new_proxy Lire::Test::Mock( 'Lire::XMLSpecContainer' ); $mock->set_result( 'spec_path', [ "$self->{'testdir'}/reports", $self->{'tmpdir'} ] ); $self->assert_str_equals( "$self->{'testdir'}/reports/test/downloads-by-period.xml",, $mock->file_from_id( 'test', 'downloads-by-period' ) ); $self->assert_dies( qr/can't find 'test' Class.* XML specification 'unknown' in "$self->{'testdir'}\/reports:$self->{'tmpdir'}/, sub { $mock->file_from_id( 'test', 'unknown' ) } ); } sub test_has_spec { my $self = $_[0]; my $mock = new_proxy Lire::Test::Mock( 'Lire::XMLSpecContainer' ); $mock->set_result( 'spec_path', [ "$self->{'testdir'}/reports" ] ); $self->assert( $mock->has_spec( 'test', 'downloads-by-period' ) ? 1 : 0, 'has_spec()' ); $self->assert( ! $mock->has_spec( 'test', 'no-such-file' ) ? 1 : 0, '!has_error' ); } sub test_list_specs { my $self = $_[0]; my $mock = new_proxy Lire::Test::Mock( 'Lire::XMLSpecContainer' ); $mock->set_result( 'spec_path', [ "$self->{'testdir'}/reports", "$self->{'tmpdir'}" ] ); mkdir "$self->{'tmpdir'}/test/", 0777 or $self->error( "mkdir failed: $!" ); create_file( "$self->{'tmpdir'}/test/a-test.xml", "" ); $self->assert_deep_equals( [ sort qw/ avg-file_size-by-timeslot downloads-by-period sessions-by-length sessions-by-user_class top-dirs top-dirs2 top-files user-downloads-utf8 user_downloads-report a-test / ], [ sort @{$mock->list_specs( 'test' ) } ] ); } 1; ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/OutputJobTest.pm�����������������������������������������������������������0000644�0001750�0001750�00000015673�10460672577�015232� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::OutputJobTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::OutputJob; use Lire::OutputFormat; use Time::Local; use Lire::Test::Mock; use Lire::PluginManager; use MIME::Entity; use MIME::Parser; use Lire::Utils qw/tempdir create_file /; sub new { my $self = shift()->SUPER::new( @_ ); $self->{'mock_output'} = new_proxy Lire::Test::Mock( 'Lire::OutputFormat' ); $self->{'mock_output'}->set_result( 'name' => 'mock', 'title' => 'Mock OuputFormat', 'mime_report' => '', 'format_report' => '', ); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'spec'} = $self->lire_default_config_spec(); $self->{'cfg'}{'_lr_config_spec'} = $self->{'spec'}; $self->set_up_plugin_mgr(); Lire::PluginManager->register_plugin( $self->{'mock_output'} ); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub test_new_invalid { my $self = $_[0]; $self->assert_dies( qr/'type' parameter should be one of 'email' or 'file'/, sub { new Lire::OutputJob( 'type', 'type', '' ) } ); } sub test_new_file { my $self = $_[0]; my $file = '/var/www/report-%Y-%m-%d'; my $cfg = {}; my $job = new Lire::OutputJob( 'file', $self->{'mock_output'}, $cfg, 'file' => $file ); $self->assert_isa( 'Lire::FileOutputJob', $job ); $self->assert_str_equals( $self->{'mock_output'}, $job->{'_format'} ); $self->assert_str_equals( $self->{'mock_output'}, $job->format() ); $self->assert_str_equals( $cfg, $job->{'_format_cfg'} ); $self->assert_str_equals( $cfg, $job->format_cfg() ); $self->assert_str_equals( $file, $job->{'_file'} ); $self->assert_str_equals( $file, $job->file() ); } sub test_output_file { my $self = $_[0]; my $jan7_2004 = timelocal( 0, 0, 0, 7, 0, 2004 ); my $file = '/var/www/report-%Y-%m-%d'; my $job = new Lire::OutputJob( 'file', $self->{'mock_output'}, '', 'file' => $file ); $self->assert_str_equals( '/var/www/report-2004-01-07', $job->output_file( $jan7_2004 ) ); } sub test_new_email { my $self = $_[0]; my $emails = [ 'flacoste@logreport.org', 'wolfgang@logreport.org' ]; my $job = new Lire::OutputJob( 'email', $self->{'mock_output'}, {}, 'emails' => $emails, 'subject' => 'A subject', ); $self->assert_isa( 'Lire::EmailOutputJob', $job ); $self->assert_str_equals( $self->{'mock_output'}, $job->{'_format'} ); $self->assert_str_equals( $self->{'mock_output'}, $job->format() ); $self->assert_str_equals( 'A subject', $job->{'_subject'} ); $self->assert_str_equals( 'A subject', $job->subject() ); $self->assert_deep_equals( $emails, $job->{'_emails'} ); $self->assert_deep_equals( $emails, [ $job->emails() ] ); } sub test_email_run { my $self = $_[0]; $self->{'cfg'}{'lr_mail_from'} = 'responder@logreport.org'; $self->{'cfg'}{'lr_mail_reply_to'} = 'admin@logreport.org'; my $cfg = {}; my $tmpdir = tempdir( $self->name() . "_XXXXXX", 'CLEANUP' => 1 ); create_file( "$tmpdir/signature.txt", "My signature\n" ); my $job = new Lire::OutputJob( 'email', $self->{'mock_output'}, $cfg, 'emails' => [ 'flacoste@logreport.org' ], 'subject' => "LogReport's \\ \"subject\"", 'extra_file' => "$tmpdir/signature.txt" ); $self->{'mock_output'}->set_result( 'mime_report' => MIME::Entity->build( 'Type' => 'text/plain', 'Data' => "A test\n" ) ); create_file( "$tmpdir/sendmail", "#! /bin/sh\nexec cat >$tmpdir/email" ); chmod 0755, "$tmpdir/sendmail"; $self->{'cfg'}{'sendmail_path'} = "$tmpdir/sendmail"; $job->run( 'report.xml' ); $self->assert_deep_equals( [ $self->{'mock_output'}, 'report.xml', $cfg, ], $self->{'mock_output'}->get_invocation( 'mime_report' ) ); my $parser = new MIME::Parser(); $parser->output_under( $tmpdir ); my $msg = $parser->parse_open( "$tmpdir/email" ); $self->assert_str_equals( 'text/plain', $msg->mime_type() ); $self->assert_str_equals( 'LogReport\'s \\ "subject"' . "\n", $msg->head()->get( 'subject' ) ); $self->assert_str_equals( 'flacoste@logreport.org' . "\n", $msg->head()->get( 'to' ) ); $self->assert_str_equals( 'responder@logreport.org' ."\n", $msg->head()->get( 'from' ) ); $self->assert_str_equals( 'admin@logreport.org' . "\n", $msg->head()->get( 'reply-to' ) ); $self->assert_str_equals( "A test\n\nMy signature\n", $msg->bodyhandle()->as_string() ); $self->{'mock_output'}->set_result( 'mime_report' => MIME::Entity->build( 'Type' => 'multipart/related' ) ); $job->run( 'report.xml' ); $msg = $parser->parse_open( "$tmpdir/email" ); $self->assert_str_equals( 'multipart/mixed', $msg->mime_type() ); $self->assert_num_equals( 2, scalar $msg->parts() ); $self->assert_str_equals( "multipart/related", $msg->parts(0)->mime_type() ); $self->assert_str_equals( 'text/plain', $msg->parts(1)->mime_type() ); $self->assert_str_equals( "My signature\n", $msg->parts(1)->bodyhandle()->as_string() ); } sub test_file_run { my $self = $_[0]; my $jan7_2004 = timelocal( 0, 0, 0, 7, 0, 2004 ); my $file = '/var/www/report-%Y-%m-%d'; my $cfg = {}; my $job = new Lire::OutputJob( 'file', $self->{'mock_output'}, $cfg, 'file' => $file ); $job->run( 'report.xml', $jan7_2004 ); $self->assert_deep_equals( [ $self->{'mock_output'}, 'report.xml', '/var/www/report-2004-01-07', $cfg, ], $self->{'mock_output'}->get_invocation( 'format_report' ) ); } sub test_new_from_config { my $self = $_[0]; my $job = $self->{'spec'}->get( 'report_jobs' )->get( 'report_job' )->get( 'schedules' )->get( 'schedule' )->get( 'output_jobs' )->get( 'output_job' )->instance(); $job->get( 'name' )->set( 'myJob' ); $job->get( 'format' )->set_plugin( 'mock' ); $job->get( 'destination' )->set_plugin( 'file' ); $job->get( 'destination' )->get( 'file' )->set( 'report.txt' ); my $jobObject = $job->as_value(); $self->assert_isa( 'Lire::FileOutputJob', $jobObject ); $self->assert_isa( 'Lire::OutputFormat', $jobObject->{'_format'} ); } 1; ���������������������������������������������������������������������lire-2.1.1/all/lib/tests/OutputFormatsTextTest.pm���������������������������������������������������0000644�0001750�0001750�00000005220�10460672601�016747� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::OutputFormatsTextTest; use strict; use base qw/Lire::Test::PluginTestCase/; use Lire::OutputFormats::Text; use Lire::Config::OutputFormatSpec; use Lire::PluginManager; use Lire::Utils qw/tempdir/; use File::Basename qw/dirname/; use File::Path qw/rmtree/; use Lire::Test::Mock; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'testdir'} = dirname( __FILE__ ) ; $self->{'output_cfg'} = new Lire::Config::OutputFormatSpec( 'name' => 'output' )->instance(); $self->{'tmpdir'} = tempdir( $self->name() . '_XXXXXX' ); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); Lire::Test::Mock->reset_factories(); rmtree( $self->{'tmpdir'} ) unless $self->{'keep_tmpdir'}; } sub create_plugin { return new Lire::OutputFormats::Text(); } sub properties_spec_file { return dirname( __FILE__ ) . "/../Lire/OutputFormats/of_txt.xml"; } sub registration_file { return dirname( __FILE__ ) . "/../Lire/OutputFormats/of_txt_init"; } sub test_format_report { my $self = $_[0]; $self->test_registration_file(); Lire::Test::Mock->set_mock_factory( 'Lire::ReportParser::AsciiWriter', 'parsefile' => '' ); my $txt = Lire::PluginManager->get_plugin( 'output_format', 'txt' ); my $report = "$self->{'tmpdir'}/report.txt"; $txt->format_report( "$self->{'testdir'}/data/test-sqlite.xml", $report, { 'encoding' => 'iso-8859-1' } ); $self->assert( -f $report, "$report should exists" ); my ($writer) = @{Lire::Test::Mock->mock_instances( 'Lire::ReportParser::AsciiWriter' )}; my ( $pkg, %args ) = @{$writer->get_invocation( 'new' )}; $self->assert_str_equals( 'iso-8859-1', $args{'encoding'} ); $self->assert_num_equals( 1, $writer->invocation_count( 'parsefile' ) ); } sub test_mime_report { my $self = $_[0]; $self->test_registration_file(); Lire::Test::Mock->set_mock_factory( 'Lire::ReportParser::AsciiWriter', 'parsefile' => '' ); my $txt = Lire::PluginManager->get_plugin( 'output_format', 'txt' ); my $entity = $txt->mime_report( "$self->{'testdir'}/data/test-sqlite.xml", { 'encoding' => 'iso-8859-1' } ); $self->assert_isa( 'MIME::Entity', $entity ); $self->assert_str_equals( 'text/plain', $entity->head()->mime_type() ); $self->assert_str_equals( "quoted-printable\n", $entity->head()->get( 'content-transfer-encoding' ) ); $self->assert_str_equals( 'iso-8859-1', $entity->head()->mime_attr( 'content-type.charset' ) ); } 1; ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/ChartTypesStackTest.pm�����������������������������������������������������0000644�0001750�0001750�00000011036�10460672577�016340� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::ChartTypesStackTest; use strict; use base qw/Lire::Test::PluginTestCase/; use Lire::ChartTypes::Stack; use Lire::Config::Build qw/ac_info/; use Lire::Config::ChartSpec; use Lire::Config::ExecutableSpec; use Lire::PluginManager; use Lire::ReportParser::ReportBuilder; use Lire::Utils qw/tempdir/; use File::Basename qw/dirname/; use IO::Scalar; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'cfg'}{'ploticus_path'} = new Lire::Config::ExecutableSpec( 'name' => 'ploticus_path' )->instance( 'value' => ac_info( 'PLOTICUS' ) ); $self->{'cfg'}{'lr_chart_font'} = ''; $self->{'chart_cfg'} = new Lire::Config::ChartSpec( 'name' => 'chart' )->instance(); return; } sub create_plugin { return new Lire::ChartTypes::Stack(); } sub properties_spec_file { return dirname( __FILE__ ) . "/../Lire/ChartTypes/ct_stack.xml"; } sub registration_file { return dirname( __FILE__ ) . "/../Lire/ChartTypes/ct_stack_init"; } sub set_up_subreport { my $self = $_[0]; my $parser = new Lire::ReportParser::ReportBuilder(); my $report = $parser->parsefile( dirname( __FILE__ ) . "/data/test-sqlite.xml" ); $self->{'subreport'} = $report->subreport_by_id( 'top-files.0' ); } sub test_get_vars { my $self = $_[0]; $self->set_up_subreport(); $self->test_registration_file(); my $info = $self->{'subreport'}->table_info(); $info->set_variables_indices(); $self->{'chart_cfg'}->get( 'type' )->set_plugin( 'stack' ); my $stack = Lire::PluginManager->get_plugin( 'chart_type', 'stack' ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'file' ); my $props = $self->{'chart_cfg'}->get( 'type' )->get_properties(); $props->get( 'y' )->set( 'request_total' ); $self->assert_deep_equals( [$info->column_info_by_name( 'request_total' )], $stack->get_vars( $self->{'chart_cfg'} ) ); $props->get( 'y3' )->set( 'request_ratio' ); $self->assert_deep_equals( [$info->column_info_by_name( 'request_total' ), $info->column_info_by_name( 'request_ratio' )], $stack->get_vars( $self->{'chart_cfg'} ) ); } sub test_write_parameters { my $self = $_[0]; $self->set_up_subreport(); my $fh = new IO::Scalar(); my $buf = $fh->sref(); $self->test_registration_file(); my $info = $self->{'subreport'}->table_info(); $info->set_variables_indices(); $self->{'chart_cfg'}->get( 'type' )->set_plugin( 'stack' ); my $stack = Lire::PluginManager->get_plugin( 'chart_type', 'stack' ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'file' ); my $props = $self->{'chart_cfg'}->get( 'type' )->get_properties(); $props->get( 'y' )->set( 'request_total' ); $stack->write_parameters( $self->{'chart_cfg'}, $fh ); my @stack = split /\n/, $$buf; $self->assert_str_equals( '#set stubvert = yes', $stack[-3] ); $self->assert_str_equals( '#set stackarea = no', $stack[-2] ); $self->assert_str_equals( '#set y = 2', $stack[-1] ); $$buf = ''; $props->get( 'y2' )->set( 'request_ratio' ); $props->get( 'y4' )->set( 'request_total' ); $props->get( 'stackarea' )->set( 1 ); $stack->write_parameters( $self->{'chart_cfg'}, $fh ); @stack = split /\n/, $$buf; $self->assert_str_equals( '#set stackarea = yes', $stack[-4] ); $self->assert_str_equals( '#set y = 2', $stack[-3] ); $self->assert_str_equals( '#set y2 = 3', $stack[-2] ); $self->assert_str_equals( '#set y4 = 4', $stack[-1] ); } sub test_write_chart { my $self = $_[0]; $self->set_up_subreport(); my $keep = $ENV{'KEEP_CHART'} || 0; $self->test_registration_file(); $self->{'chart_cfg'}->get( 'name' )->set( 'stack' ); $self->{'chart_cfg'}->get( 'title' )->set( $self->{'subreport'}->title() ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'file' ); $self->{'chart_cfg'}->get( 'type' )->set_plugin( 'stack' ); my $props = $self->{'chart_cfg'}->get( 'type' )->get_properties(); $props->get( 'y' )->set( 'request_total' ); $props->get( 'y2' )->set( 'request_ratio' ); my $stack = Lire::PluginManager->get_plugin( 'chart_type', 'stack' ); my $dir = tempdir( $self->name() . '_XXXXXX', CLEANUP => !$keep ); my $chart = $stack->write_chart( $self->{'chart_cfg'}, $self->{'subreport'}, 'outputdir' => $dir, 'format' => 'png' ); $self->assert( -f $chart ? 1 : 0, "file '$chart' not created" ); warn( "\nChart written in: $chart\n" ) if $keep; } 1; ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/UtilsTest.pm���������������������������������������������������������������0000644�0001750�0001750�00000073375�10460672600�014365� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::UtilsTest; use strict; use base qw/ Lire::Test::TestCase /; use File::Spec; use Lire::Utils qw/xml_encode latex_encode diff_lists tilde_expand tmpdir tempfile tempdir min max ratio ratio100 shell_quote file_content create_file sql_quote_name tree_apply item_index deep_copy check_param check_object_param indent period_range text_for_width is_url parse_url unique /; use Time::Local; #our @TESTS = qw//; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub test_xml_encode { my $self = $_[0]; my $v = xml_encode( "<XML> & </XML> Joe \"Such\" a Friend's birtday" ); $self->assert_equals( "<XML> & </XML> Joe "Such" a Friend's birtday", $v ); } sub test_latex_encode { my $self = $_[0]; $self->assert_str_equals( '\\# \\$ \\& \\~{} \\_ \\^{} \\% \\{ \\} $\\backslash$ Other $[$ $]$ $<$ $>$', latex_encode( '# $ & ~ _ ^ % { } \\ Other [ ] < >' ) ); } sub test_diff_lists { my $self = $_[0]; my $diff = diff_lists( [qw/field1 field2 field3 field4/], [qw/field4 field3 field2 field1/] ); $self->assert_null( $diff, "should have found no diffs" ); $diff = diff_lists( [qw/field1 field2 field3 field4/], [qw/field3 field2 field4 field5/], ); $self->assert_not_null( $diff, "should have found diffs" ); $self->assert_deep_equals( [ "field1" ], $diff->{'remove'} ); $self->assert_deep_equals( [ "field5" ], $diff->{'new'} ); $diff = diff_lists( [qw/field1 field2 field3 field4/], [qw/field6 field3 field2 field4 field5/], ); $self->assert_not_null( $diff, "should have found diffs" ); $self->assert_deep_equals( [ "field1" ], $diff->{'remove'} ); $self->assert_deep_equals( [ "field5", "field6" ], $diff->{'new'} ); } sub test_tilde_expansion { my $self = $_[0]; my $home = $ENV{'HOME'}; $self->assert_equals($home, tilde_expand('~')); $self->assert_equals("$home/", tilde_expand('~/')); $self->assert_equals("$home/~", tilde_expand('~/~')); $self->assert_equals("$home/~/", tilde_expand('~/~/')); $self->assert_equals('/~', tilde_expand('/~')); $self->assert_equals('/~/', tilde_expand('/~/')); my $user = 'uioxzcyo'; $self->assert_equals("~$user", tilde_expand("~$user")); $self->assert_equals("~$user/", tilde_expand("~$user/")); $self->assert_equals("/$user~", tilde_expand("/$user~")); $self->assert_equals("/$user~/", tilde_expand("/$user~/")); $user = getpwuid($<); my ($name,$pass,$uid,$gid,$quota,$comment,$gecos,$dir) = getpwnam($user) or return; $self->assert_equals("$dir", tilde_expand("~$user")); $self->assert_equals("$dir/", tilde_expand("~$user/")); $self->assert_equals("/$user~", tilde_expand("/$user~")); $self->assert_equals("/$user~/", tilde_expand("/$user~/")); } sub test_min { my $self = $_[0]; $self->assert_null( min() ); $self->assert_null( min( undef, undef ) ); $self->assert_num_equals( -1, min( -1, undef) ); $self->assert_num_equals( 2, min( 2, undef) ); $self->assert_num_equals( -2, min( -1,-2, 0 ) ); $self->assert_num_equals( 0, min(0,0,0)); $self->assert_num_equals( 0, min(1,0,0)); } sub test_max { my $self = $_[0]; $self->assert_null( max() ); $self->assert_null( max( undef, undef ) ); $self->assert_num_equals( 1, max( -1, 0, 1, undef ) ); $self->assert_num_equals( -1, max( -1, -2) ); $self->assert_num_equals( 0, max( 0, 0, 0) ); $self->assert_num_equals( -1, max( -1, undef ) ); } sub test_tmpdir { my $self = $_[0]; $self->assert_equals( File::Spec->tmpdir, tmpdir() ); { local $ENV{'TMPDIR'} = $ENV{'HOME'}; $self->assert_equals( $ENV{'HOME'}, Lire::Utils::_tmpdir() ); } } sub test_tempfile { my $self = $_[0]; my $fh = Lire::Utils::_tempfile(); $self->assert_not_null( $fh, "_tempfile() returned undef" ); $self->assert( -r $fh, "file handle isn't readable" ); $self->assert( -w $fh, "file handle isn't writeable" ); my ( $nfh, $filename ) = Lire::Utils::_tempfile( "lireXXXXXX" ); $self->assert( qr/lire[a-zA-Z0-9]{6}$/, $filename ); $self->assert( -r $nfh, "file handle isn't readable" ); $self->assert( -w $nfh, "file handle isn't writeable" ); unlink $filename; # Try with perl's standard ones. (PerlUnit only works with perl 5.6.1 and # later my $pfh = tempfile(); $self->assert_not_null( $pfh, "tempfile() returned undef" ); $self->assert( -r $pfh, "file handle isn't readable" ); $self->assert( -w $pfh, "file handle isn't writeable" ); my ( $pnfh, $pfilename ) = tempfile( "lireXXXXXX" ); $self->assert( qr/lire[a-zA-Z0-9]{6}$/, $pfilename ); $self->assert( -r $pnfh, "file handle isn't readable" ); $self->assert( -w $pnfh, "file handle isn't writeable" ); unlink $pfilename; } sub test_tempdir { my $self = $_[0]; my $tmpdir = Lire::Utils::_tempdir(); $self->assert_not_null( $tmpdir, "_tempdir() returned undef" ); $self->assert( -r $tmpdir, "tempory dir isn't readable" ); $self->assert( -w $tmpdir, "tempory dir isn't writeable" ); $self->assert( -x $tmpdir, "tempory dir isn't searchable" ); rmdir $tmpdir; $tmpdir = Lire::Utils::_tempdir( "lireXXXXXX" );; $self->assert_not_null( $tmpdir, "_tempdir() returned undef" ); $self->assert( qr/lire[a-zA-Z0-9]{6}$/, $tmpdir ); $self->assert( -r $tmpdir, "tempory dir isn't readable" ); $self->assert( -w $tmpdir, "tempory dir isn't writeable" ); $self->assert( -x $tmpdir, "tempory dir isn't searchable" ); rmdir $tmpdir; # Try with perl's standard ones. (PerlUnit only works with perl 5.6.1 and # later my $ptmpdir = tempdir(); $self->assert_not_null( $ptmpdir, "tempdir() returned undef" ); $self->assert( -r $ptmpdir, "tempory dir isn't readable" ); $self->assert( -w $ptmpdir, "tempory dir isn't writeable" ); $self->assert( -x $ptmpdir, "tempory dir isn't searchable" ); rmdir $ptmpdir; $ptmpdir = tempdir( "lireXXXXXX" );; $self->assert_not_null( $ptmpdir, "_tmpdir() returned undef" ); $self->assert( qr/lire[a-zA-Z0-9]{6}$/, $ptmpdir ); $self->assert( -r $ptmpdir, "tempory dir isn't readable" ); $self->assert( -w $ptmpdir, "tempory dir isn't writeable" ); $self->assert( -x $ptmpdir, "tempory dir isn't searchable" ); rmdir $ptmpdir; } sub test_ratio { my $self = $_[0]; $self->assert_equals( 2, ratio( 10, 5 ) ); # Force string comparison since NaN == NaN is false $self->assert_str_equals( "NaN", ratio( 10, 0 ) ); $self->assert_equals( 0, ratio( 0, 10 ) ); $self->assert_equals( "3.33", ratio( 10, 3 ) ); } sub test_ratio100 { my $self = $_[0]; $self->assert_equals( 50, ratio100( 5, 10 ) ); # Force string comparison since NaN == NaN is false $self->assert_str_equals( "NaN", ratio100( 0, 0 ) ); $self->assert_equals( 0, ratio100( 0, 10 ) ); $self->assert_equals( "33.3", ratio100( 3333, 10000 ) ); } sub test_shell_quote { my $self = $_[0]; $self->assert_equals( "''", shell_quote( undef ) ); $self->assert_equals( "'Test'", shell_quote( 'Test' ) ); $self->assert_equals( q{'Test'\'''}, shell_quote( "Test'" ) ); $self->assert_equals( q{'`echo shell'\''s test`'}, shell_quote( "`echo shell's test`" ) ); } sub test_file_content { my $self = $_[0]; my $content = <<EOF; This is the file content. More than one line. EOF my ($fh, $name ) = File::Temp::tempfile(); print $fh $content; close $fh; $self->assert_dies( qr/missing 'filename' parameter/, sub { file_content() } ); $self->assert_dies( qr{could not open '/no/such/file' for reading}, sub { file_content( "/no/such/file" ) } ); $self->assert_equals( $content, file_content( $name ) ); unlink $name; } sub test_create_file { my $self = $_[0]; no warnings 'redefine'; my $encoding = undef; my $set_fh_encoding = sub { $encoding = 1; }; local *Lire::I18N::set_fh_encoding = $set_fh_encoding; $self->assert_died( sub { create_file()}, qr/missing 'filename' parameter/ ); $self->assert_died( sub { create_file( "/no/such/file" ) }, qr/error creating.*: No such file/ ); my $content = <<EOF; This is a file. And its content. EOF my $tmpdir = File::Temp::tempdir( "Utils_XXXXXX", 'CLEANUP' => 1 ); my $filename = "$tmpdir/test_file"; create_file( $filename ); $self->assert( -f $filename, "$filename wasn't created" ); $self->assert( ! -s $filename, "$filename should be empty" ); create_file( $filename, $content ); my $fh; open $fh, $filename or $self->error( "open failed: $!" ); local $/; my $new_content = <$fh>; close $fh; $self->assert_equals( $content, $new_content ); $self->assert_null( $encoding ); create_file( $filename, $content, 1 ); $self->assert_num_equals( 1, $encoding ); return; } sub test_sql_quote_name { my $self = $_[0]; $self->assert_equals( 'field_name', sql_quote_name( 'field_name' ) ); $self->assert_equals( '"field-name"', sql_quote_name( 'field-name' ) ); $self->assert_equals( '"field.name"', sql_quote_name( 'field.name' ) ); $self->assert_equals( '"field:name"', sql_quote_name( 'field:name' ) ); } sub set_up_tree { my $self = $_[0]; my $root = new tests::node(); my @nodes = ( $root ); for ( 1..3) { push @nodes, new tests::node( $root ); } for ( 1..3 ) { push @nodes, new tests::node( $nodes[$_] ); push @nodes, new tests::node( $nodes[$_] ); } $self->assert_equals( 10, scalar @nodes ); return ( $root, \@nodes ); } sub test_tree_apply_bad_params { my $self = $_[0]; $self->assert_died( sub { tree_apply() }, qr/missing 'root' parameter/ ); $self->assert_died( sub { tree_apply( {}, ) }, qr/missing 'children_func' parameter/ ); $self->assert_died( sub { tree_apply( {}, sub {} ) }, qr/missing 'apply_func' parameter/ ); } sub test_tree_apply_subref { my $self = $_[0]; my ( $root, $nodes ) = $self->set_up_tree(); my $preorder_nodes = [ $nodes->[0], $nodes->[0]{'children'}[0], $nodes->[0]{'children'}[0]{'children'}[0], $nodes->[0]{'children'}[0]{'children'}[1], $nodes->[0]{'children'}[1], $nodes->[0]{'children'}[1]{'children'}[0], $nodes->[0]{'children'}[1]{'children'}[1], $nodes->[0]{'children'}[2], $nodes->[0]{'children'}[2]{'children'}[0], $nodes->[0]{'children'}[2]{'children'}[1], ]; my $idx = 1; my $result = tree_apply( $root, sub { $_[0]->{'children'} }, sub { $_[0]{'flag'} = $idx++ } ); my $e_result = [ 1 .. 10 ]; $self->assert_deep_equals( $e_result, $result ); for ( my $i=0; $i < @$preorder_nodes; $i++ ) { $self->assert_equals( $e_result->[$i], $preorder_nodes->[$i]{'flag'} ); } } sub test_tree_apply_method { my $self = $_[0]; my ( $root, $nodes ) = $self->set_up_tree(); my $result = tree_apply( $root, 'children', 'set_flag' ); $self->assert_deep_equals( [ ( 1 ) x 10 ], $result ); foreach my $n ( @$nodes ) { $self->assert_equals( 1, $n->{'flag'} ); } } sub test_item_index { my $self = $_[0]; my $ref = {}; my $array = [ 'wawa', 2, $ref, 4.0 ]; $self->assert_died( sub { item_index() }, qr/missing 'array' parameter/ ); $self->assert_died( sub { item_index( {} ) }, qr/'array' should be an array ref, not 'HASH/ ); #' $self->assert_died( sub { item_index( [] ) }, qr/missing 'item' parameter/ ); $self->assert_num_equals( 0, item_index( $array, 'wawa' ) ); $self->assert_num_equals( 1, item_index( $array, '2' ) ); $self->assert_num_equals( 2, item_index( $array, $ref ) ); $self->assert_num_equals( 3, item_index( $array, 4 ) ); $self->assert_null( undef, item_index( $array, 'cocotte' ) ); } sub test_deep_copy { my $self = $_[0]; $self->assert_died( sub { deep_copy() }, qr/missing 'object' parameter/ ); $self->assert_str_equals( 'Test', deep_copy( 'Test' ) ); $self->assert_died( sub { deep_copy( 'Test', {} ) }, qr/'exclusions' should be an array reference, not 'HASH/ ); my $array = [ 1, 'string', [ 2, undef, 4 ] ]; $self->assert_deep_equals( $array, deep_copy( $array ) ); $self->assert_str_not_equals( $array, deep_copy( $array ) ); my $rx = qr/.*/; $self->assert_str_equals( $rx, deep_copy( $rx ) ); my $hash = { 'key1' => $array, 'key2' => 1, 'key3' => $array, }; $hash->{'key4'} = $hash; # cyclic reference my $copy = deep_copy( $hash ); $self->assert_deep_equals( $hash, $copy ); $self->assert_str_not_equals( $hash, $copy ); $self->assert_str_not_equals( $array, $copy->{'key1'} ); $self->assert_str_equals( $copy->{'key1'}, $copy->{'key3'} ); $self->assert_str_equals( $copy, $copy->{'key4'} ); my $object = bless { 'key' => 'string1' }, 'object'; my $object_copy = deep_copy( $object ); $self->assert_str_equals( ref $object, ref $object_copy ); $self->assert_str_not_equals( $object, $object_copy ); $self->assert_deep_equals( $object, $object_copy ); } sub test_clone_scalar_ref { my $self = $_[0]; my $string = 'wawa'; my $ref1 = \$string; my $ref2 = \$ref1; my $excl = []; no warnings 'redefine'; local *Lire::Utils::_deep_copy = sub { my ( $object, $seen, $exclusions ) = @_; $self->assert_str_equals( $excl, $exclusions ); return $object unless ref $object; return $seen->{$object} if exists $seen->{$object}; if ( ref $object eq 'REF' || ref $object eq 'SCALAR') { return Lire::Utils::_clone_scalar_ref( $object, $seen,$exclusions); } else { $self->error( "ref type unsupported by deep_copy(): $object" ); } }; my $seen = {}; my $ref1_copy = Lire::Utils::_clone_scalar_ref( $ref1, $seen, $excl ); $self->assert_str_equals( $$ref1, $$ref1_copy ); $self->assert_str_not_equals( $ref1, $ref1_copy ); $self->assert_str_equals( $seen->{$ref1}, $ref1_copy ); my $ref2_copy = Lire::Utils::_clone_scalar_ref( $ref2, $seen, $excl ); $self->assert_str_equals( $$ref2_copy, $ref1_copy ); $self->assert_str_equals( $seen->{$ref2}, $ref2_copy ); } sub test_clone_array_ref { my $self = $_[0]; my $array1 = [ 1, 2, 3 ]; my $array2 = [ $array1 ]; my $excl = []; no warnings 'redefine'; local *Lire::Utils::_deep_copy = sub { my ( $object, $seen, $exclusions ) = @_; $self->assert_str_equals( $excl, $exclusions ); return $object unless ref $object; return $seen->{$object} if exists $seen->{$object}; if ( ref $object eq 'ARRAY' ) { return Lire::Utils::_clone_array_ref( $object, $seen, $exclusions); } else { $self->error( "ref type unsupported by deep_copy(): $object" ); } }; my $seen = {}; my $array1_copy = Lire::Utils::_clone_array_ref( $array1, $seen, $excl ); $self->assert_str_not_equals( $array1, $array1_copy ); $self->assert_deep_equals( $array1_copy, $array1 ); $self->assert_str_equals( $array1_copy, $seen->{$array1} ); my $array2_copy = Lire::Utils::_clone_array_ref( $array2, $seen, $excl ); $self->assert_str_equals( $array2_copy, $seen->{$array2} ); $self->assert_deep_equals( $array2_copy, $array2 ); } sub test_clone_hash_ref { my $self = $_[0]; my $hash1 = { 'key1' => 'value1', 'key2' => 'value2' }; my $hash2 = { 'key1' => 1, 'key2' => $hash1 }; my $excl = []; no warnings 'redefine'; local *Lire::Utils::_deep_copy = sub { my ( $object, $seen, $exclusions ) = @_; $self->assert_str_equals( $excl, $exclusions ); return $object unless ref $object; return $seen->{$object} if exists $seen->{$object}; if ( ref $object eq 'HASH' ) { return Lire::Utils::_clone_hash_ref( $object, $seen, $exclusions ); } else { $self->error( "ref type unsupported by deep_copy(): $object" ); } }; my $seen = {}; my $hash1_copy = Lire::Utils::_clone_hash_ref( $hash1, $seen, $excl ); $self->assert_str_not_equals( $hash1, $hash1_copy ); $self->assert_deep_equals( $hash1_copy, $hash1 ); $self->assert_str_equals( $hash1_copy, $seen->{$hash1} ); my $hash2_copy = Lire::Utils::_clone_hash_ref( $hash2, $seen, $excl ); $self->assert_str_equals( $hash2_copy, $seen->{$hash2} ); $self->assert_deep_equals( $hash2_copy, $hash2 ); } sub test_clone_object { my $self = $_[0]; my $scalar = 'Test'; my $scalar_object = bless \$scalar, 'scalar'; my $array_object = bless [], 'array'; my $glob_object = bless \*SYMBOL, 'symbol'; my $object1 = bless { 'key1' => 1 }, "package1"; my $object2 = bless { 'key1' => $object1 }, 'package2'; $self->assert_died( sub { Lire::Utils::_clone_object( $glob_object, {} ) }, qr/unsupported object storage: 'symbol=GLOB/ ); my $seen = {}; my $ob1_copy = Lire::Utils::_clone_object( $object1, $seen ); $self->assert_str_not_equals( $object1, $ob1_copy ); $self->assert_str_equals( ref $object1, ref $ob1_copy ); $self->assert_deep_equals( $object1, $ob1_copy ); $self->assert_str_equals( $ob1_copy, $seen->{$object1} ); my $ob2_copy = Lire::Utils::_clone_object( $object2, $seen ); $self->assert_str_equals( $ob2_copy, $seen->{$object2} ); $self->assert_deep_equals( $ob2_copy, $object2 ); $self->assert_str_equals( $object2, Lire::Utils::_clone_object( $object2, $seen, [ 'package2' ] ) ); } sub test_check_param { my $self = $_[0]; $self->assert_died( sub { check_param() }, qr/check_param needs at least 2 arguments: a parameter, the parameter\'s name/ ); $self->assert_died( sub { check_param( undef, 'wawa&' ) }, qr/parameter 'name' is not a valid name: 'wawa&'/ ); $self->assert_died( sub { check_param( undef, 'wawa' ) }, qr/missing \'wawa\' parameter/ ); $self->assert_died( sub { check_param( '123', 'wawa', qr/^[a-z]+$/ ) }, qr/\'wawa\' parameter doesn\'t match \'\(.*\)': \'123\'/ ); $self->assert_died( sub { check_param( 'abc', 'wawa', qr/^[0-9]+$/, "'wawa' parameter is not a valid integer" )}, qr/\'wawa\' parameter is not a valid integer: \'abc\'/ ); $self->assert_died( sub { check_param( 0, 'wawa', sub { return $_[0] }, "'wawa' parameter is false" )}, qr/\'wawa\' parameter is false: \'0\'/ ); check_param( 1, 'wawa', sub { return $_[0] }, "This test of check_param should have passed" ); return; } sub test_check_object_param { my $self = $_[0]; my $test_obj = bless {}, 'TestClass'; $self->assert_died( sub { check_object_param() }, qr/check_object_param needs 3 arguments: an object, the object parameter\'s name, the object's class name/ ); $self->assert_died( sub { check_object_param( $test_obj, 'wawaobj&', [ 'WawaClass' ] ) }, qr/parameter 'name' is not a valid name: 'wawaobj&'/ ); $self->assert_died( sub { check_object_param( $test_obj, 'wawaobj', 'WawaClass&' ) }, qr/parameter 'class' contains an invalid class name: 'WawaClass&'/ ); $self->assert_died( sub { check_object_param( $test_obj, 'wawaobj', [ 'WawaClass&' ] ) }, qr/parameter 'class' contains an invalid class name: 'WawaClass&'/ ); $self->assert_died( sub { check_object_param( $test_obj, 'wawaobj', [ 'Wawa:Class' ] ) }, qr/parameter 'class' contains an invalid class name: 'Wawa:Class'/ ); $self->assert_died( sub { check_object_param( $test_obj, 'wawaobj', [ 'Wawa:::Class' ] ) }, qr/parameter 'class' contains an invalid class name: 'Wawa:::Class'/ ); $self->assert_died( sub { check_object_param( 'wawa', 'wawaname', [ 'wawaclass' ] ) }, qr/'wawaname' parameter should be a 'wawaclass' instance, not \'wawa\'/ ); $self->assert_died( sub { check_object_param( $test_obj, 'wawa', 'WawaClass' ) }, qr/'wawa' parameter should be a 'WawaClass' instance, not 'TestClass/ ); $self->assert_died( sub { check_object_param( $test_obj, 'wawa', [ 'WawaClass' ] ) }, qr/'wawa' parameter should be a 'WawaClass' instance, not 'TestClass/ ); $self->assert_died( sub { check_object_param( $test_obj, 'wawa', [ 'WawaClass', 'Chill::Class', 'Mega::Class::Name' ] ) }, qr/'wawa' parameter should be a 'WawaClass', 'Chill::Class' or 'Mega::Class::Name' instance, not 'TestClass/ ); $self->assert_died( sub { check_object_param( $test_obj, 'wawa', [] )}, qr/parameter \'class\' should contain at least one class name/ ); my $rc = check_object_param( $test_obj, 'wawaobj', [ 'TestClass' ] ); $self->assert_null( $rc, "there should be no return code" ); check_object_param( bless ({}, 'Test::Class') , 'wawaobj', [ 'Test::Class' ] ); return; } sub _check_object_param_fail_method { my ( $self, $object ); check_object_param( $object, 'test_object', [ 'tests::UtilsTest' ] ); } sub test_check_object_param_caller { my $self = $_[0]; # check_object_param() invocations with a wrong object instance should # return the method's caller informations (1st check) while bad parameters # given to check_object_param() itself should refer to the # check_object_param's caller (2nd check). my $this_file = 'nofile'; my $this_line = 'noline'; eval { $this_file = __FILE__; $this_line = __LINE__; _check_object_param_fail_method( undef ); }; my $err = $@; $self->assert_not_null( $err, "no error message??" ); $self->assert_matches( qr/^missing 'test_object' parameter at $this_file:$this_line$/, $err ); eval { $this_file = __FILE__; $this_line = __LINE__; check_object_param();}; $err = $@; $self->assert_not_null( $err, "no error message??" ); $self->assert_matches( qr/^check_object_param needs 3 arguments: an object, the object parameter's name, the object's class name at $this_file:$this_line$/, $err ); return; } sub test_indent { my $self = $_[0]; $self->assert_str_equals( '', indent() ); $self->assert_str_equals( '', indent( '' ) ); my $start_text = 'simple line'; $self->assert_str_equals( ' simple line', indent( $start_text ) ); $start_text = <<_EOT; text for indentation indented line end of indentation _EOT my $e_text = <<_EOT; text for indentation indented line end of indentation _EOT $self->assert_str_equals( $e_text, indent( $start_text ) ); $e_text = <<_EOT; text for indentation indented line end of indentation _EOT $self->assert_str_equals( $e_text, indent( $start_text, 4 ) ); return; } sub test_period_range { my $self = $_[0]; $self->{'cfg'}{'lr_week_numbering'} = 'U'; $self->set_up_tz( 'UTC' ); my $dec31_2004 = timelocal( 0, 5, 23, 31, 11, 2004 ); $self->assert_dies( qr/'period' parameter should be one of 'hourly', 'daily', 'weekly', 'monthly' or 'yearly'/, sub { period_range( 'unique', $dec31_2004 ) } ); $self->assert_deep_equals( [ timelocal( 0, 0, 23, 31, 11, 2004 ), timelocal( 0, 0, 0, 1, 0, 2005 ) ], period_range( 'hourly', $dec31_2004 ) ); $self->assert_deep_equals( [ timelocal( 0, 0, 0, 31, 11, 2004 ), timelocal( 0, 0, 0, 1, 0, 2005 ) ], period_range( 'daily', $dec31_2004 ) ); $self->assert_deep_equals( [ timelocal( 0, 0, 0, 1, 11, 2004 ), timelocal( 0, 0, 0, 1, 0, 2005 ) ], period_range( 'monthly', $dec31_2004 ) ); my $jan1_2004 = timelocal( 0, 0, 0, 1, 0, 2004 ); $self->assert_deep_equals( [ timelocal( 0, 0, 0, 1, 0, 2004 ), timelocal( 0, 0, 0, 1, 1, 2004 ) ], period_range( 'monthly', $jan1_2004 ) ); $self->assert_deep_equals( [ timelocal( 0, 0, 0, 1, 0, 2004 ), timelocal( 0, 0, 0, 1, 0, 2005 ) ], period_range( 'yearly', $dec31_2004 ) ); $self->assert_deep_equals( [ timelocal( 0, 0, 0, 26, 11, 2004 ), timelocal( 0, 0, 0, 2, 0, 2005 ) ], period_range( 'weekly', $dec31_2004 ) ); } sub test_text_for_width { my $self = $_[0]; $self->assert_dies( qr/missing \'text\' parameter/, sub { text_for_width() } ); $self->assert_dies( qr/missing \'width\' parameter/, sub { text_for_width( 'wawa' ) } ); $self->assert_dies( qr/\'width' should be a positive, greater than or equal to 5, integer: \'-3\'/, sub { text_for_width( 'wawa', -3 ) } ); $self->assert_dies( qr/\'width' should be a positive, greater than or equal to 5, integer: \'wawa\'/, sub { text_for_width( 'wawa', 'wawa' ) } ); $self->assert_str_equals( 'wawa', text_for_width( 'wawa', 10 ) ); $self->assert_str_equals( 'b...s', text_for_width( 'bigwawatestormorethan9chars', 5 ) ); $self->assert_str_equals( 'big...ars', text_for_width( 'big wawa test or more than 9 chars', 9 ) ); $self->assert_str_equals( 'big...hars', text_for_width( 'big wawa test or more than 10 chars', 10 ) ); $self->assert_str_equals( 'big...test', text_for_width( 'big test', 10 ) ); } sub test_is_url { my $self = $_[0]; my $nourl_string1 = "/etc/lire"; my $nourl_string2 = "/etc/lire/file://tmp"; my $nourl_string3 = "file:/etc/lire/wawa"; my $nourl_string4 = "fi le://etc/lire/wawa"; my $url_string1 = "http://www.wawa.org"; my $url_string2 = "file:///tmp"; my $url_string3 = "file://c:/temp"; $self->assert_num_equals( 0, is_url( $nourl_string1 ) ); $self->assert_num_equals( 0, is_url( $nourl_string2 ) ); $self->assert_num_equals( 0, is_url( $nourl_string3 ) ); $self->assert_num_equals( 0, is_url( $nourl_string4 ) ); $self->assert_num_equals( 1, is_url( $url_string1 ) ); $self->assert_num_equals( 1, is_url( $url_string2 ) ); $self->assert_num_equals( 1, is_url( $url_string3 ) ); return; } sub test_parse_url { my $self = $_[0]; $self->assert_deep_equals( { 'scheme' => 'http', 'host' => 'www.logreport.org', 'port' => 80, 'path' => '/index.html', 'query' => 'search=test', 'fragment' => 'anchor' }, parse_url( 'http://www.logreport.org:80/index.html?search=test#anchor' ) ); $self->assert_deep_equals( { 'scheme' => 'http', 'host' => 'www.logreport.org', 'port' => undef, 'path' => '/index.html', 'query' => undef, 'fragment' => undef }, parse_url( 'http://www.logreport.org/index.html' ) ); $self->assert_deep_equals( { 'scheme' => undef, 'host' => undef, 'port' => undef, 'path' => '/index.html', 'query' => undef, 'fragment' => 'anchor' }, parse_url( '/index.html#anchor' ) ); } sub test_unique { my $self = $_[0]; $self->assert_deep_equals( [ 1, 2, 3 ], unique( [ 1, 2, 3, 1, 2, 3] ) ); $self->assert_deep_equals( [ 'aa', 'b', 'c' ], unique( [ 'aa', 'aa', 'aa', 'b', 'c' ] ) ); } package tests::node; sub new { my ( $pkg, $parent ) = @_; my $self = bless { 'flag' => 0, 'children' => [] }, $pkg; push @{$parent->{'children'}}, $self if defined $parent; return $self; } sub children { return $_[0]{'children'}; } sub set_flag { return $_[0]{'flag'} = 1; } 1; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/ConfigCompoundSpecTest.pm��������������������������������������������������0000644�0001750�0001750�00000011270�10460672577�017011� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::ConfigCompoundSpecTest; use strict; use tests::ConfigSpecTest; use base qw/tests::ConfigTypeSpecBase/; sub test_new_is_array { my $self = $_[0]; my $spec = $self->{'spec'}; $self->assert_isa( 'Lire::Config::CompoundSpec', $spec ); $self->assert_str_equals( 'ARRAY', ref $spec->{'components'} ); $self->assert_str_equals( 'HASH', ref $spec->{'index'} ); my $str_spec = new Lire::Config::StringSpec( 'name' => 'subspec1' ); $spec->add( $str_spec ); my $int_spec = new Lire::Config::IntegerSpec( 'name' => 'subspec2' ); $spec->add( $int_spec ); $self->assert_deep_equals( [ $str_spec, $int_spec ], $spec->{'components'} ); return; } sub test_add { my $self = $_[0]; $self->assert_equals( 0, scalar $self->{'spec'}->components() ); my $string = new Lire::Config::StringSpec( 'name' => "test" ); $self->{'spec'}->add( $string ); $self->assert_dies( qr/already contains a component named \'test\'/, sub { $self->{'spec'}->add( $string ) } ); $self->assert_str_equals( $string, $self->{'spec'}->get( 'test' )); $self->assert_num_equals( 0, $self->{'spec'}{'index'}{'test'} ); my $int = new Lire::Config::IntegerSpec( 'name' => "int" ); $self->{'spec'}->add( $int ); $self->assert_str_equals( $int, $self->{'spec'}->get( "int" ) ); $self->assert_num_equals( 1, $self->{'spec'}{'index'}{'int'} ); $self->assert_dies( qr/missing \'type\' parameter/, sub { $self->{'spec'}->add( undef ) } ); $self->assert_dies( qr/\'type\' parameter should be a \'Lire::Config::TypeSpec\' instance, not \'Lire::Config::Scalar/, sub {$self->{'spec'}->add( new Lire::Config::Scalar( 'spec' => $self->{'spec'} ) ) } ); } sub test_label_component { my $self = $_[0]; my $spec = $self->{'spec'}; my $str_spec = new Lire::Config::StringSpec( 'name' => 'subspec1' ); $spec->add( $str_spec ); $spec->{'label'} = 'subspec1'; $self->assert_str_equals( 'subspec1', $spec->label_component() ); $spec->{'label'} = undef; $self->assert_null( $spec->label_component() ); $spec->{'label'} = 'wawa'; $self->assert_dies( qr/\'wawa\' component does not exist/, sub { $spec->label_component() } ); my $new_spec = new Lire::Config::CompoundSpec( 'name' => 'new_wawa', 'label' => 'subspec1' ); $self->assert_dies( qr/\'subspec1\' component does not exist/, sub { $new_spec->label_component() } ); $new_spec->add( $str_spec ); $self->assert_str_equals( 'subspec1', $new_spec->label_component() ); return; } sub test_has_component { my $self = $_[0]; my $spec = $self->{'spec'}; my $string = new Lire::Config::StringSpec( 'name' => 'test_str' ); $self->{'spec'}->add( $string ); my $integer = new Lire::Config::IntegerSpec( 'name' => 'test_int' ); $self->{'spec'}->add( $integer ); $self->assert( $spec->has_component( 'test_str' ) ); $self->assert( $spec->has_component( 'test_int' ) ); $self->assert( ! $spec->has_component( 'wawa' ) ); $self->assert_dies( qr/missing \'name\' parameter/, sub { $spec->has_component() } ); } sub test_components { my $self = $_[0]; my $spec = $self->{'spec'}; $self->assert_num_equals( 0, scalar $spec->components() ); my $string = new Lire::Config::StringSpec( 'name' => 'test_str' ); $self->{'spec'}->add( $string ); $self->assert_num_equals( 1, scalar $spec->components() ); my $integer = new Lire::Config::IntegerSpec( 'name' => 'test_int' ); $self->{'spec'}->add( $integer ); $self->assert_num_equals( 2, scalar $spec->components() ); $self->assert_deep_equals( [ $string, $integer ], [ $spec->components() ] ); $self->assert_num_equals( 0, $spec->{'index'}{'test_str'} ); $self->assert_num_equals( 1, $spec->{'index'}{'test_int'} ); $self->assert_str_equals( $integer, $spec->{'components'}[ $spec->{'index'}{'test_int'} ] ); } sub test_get { my $self = $_[0]; $self->assert_dies( qr/missing \'name\' parameter/, sub { $self->{'spec'}->get( undef ) } ); $self->assert_dies( qr/invalid \'name\' parameter: \'\'/, sub { $self->{'spec'}->get( '' ) } ); $self->assert_dies( qr/invalid \'name\' parameter: \'\$%\'/, sub { $self->{'spec'}->get( '$%' ) } ); $self->assert_dies( qr/no component named \'param\'/, sub { $self->{'spec'}->get( 'param' ) } ); } sub type { return "Lire::Config::CompoundSpec"; } 1; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/ChartTypesPieTest.pm�������������������������������������������������������0000644�0001750�0001750�00000005560�10460672577�016015� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::ChartTypesPieTest; use strict; use base qw/Lire::Test::PluginTestCase/; use Lire::ChartTypes::Pie; use Lire::Config::Build qw/ac_info/; use Lire::Config::ChartSpec; use Lire::Config::ExecutableSpec; use Lire::PluginManager; use Lire::ReportParser::ReportBuilder; use Lire::Utils qw/tempdir/; use File::Basename qw/dirname/; use IO::Scalar; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'cfg'}{'ploticus_path'} = new Lire::Config::ExecutableSpec( 'name' => 'ploticus_path' )->instance( 'value' => ac_info( 'PLOTICUS' ) ); $self->{'cfg'}{'lr_chart_font'} = ''; $self->{'chart_cfg'} = new Lire::Config::ChartSpec( 'name' => 'chart' )->instance(); return; } sub create_plugin { return new Lire::ChartTypes::Pie(); } sub properties_spec_file { return dirname( __FILE__ ) . "/../Lire/ChartTypes/ct_pie.xml"; } sub registration_file { return dirname( __FILE__ ) . "/../Lire/ChartTypes/ct_pie_init"; } sub set_up_subreport { my $self = $_[0]; my $parser = new Lire::ReportParser::ReportBuilder(); my $report = $parser->parsefile( dirname( __FILE__ ) . "/data/test-sqlite.xml" ); $self->{'subreport'} = $report->subreport_by_id( 'top-files.0' ); } sub test_write_parameters { my $self = $_[0]; $self->set_up_subreport(); $self->test_registration_file(); $self->{'chart_cfg'}->get( 'type' )->set_plugin( 'pie' ); my $pie = Lire::PluginManager->get_plugin( 'chart_type', 'pie' ); my $fh = new IO::Scalar; my $buf = $fh->sref(); $self->{'subreport'}->table_info()->set_variables_indices(); $self->{'chart_cfg'}->type_properties()->get( 'values' )->set( 'request_total' ); $pie->write_parameters( $self->{'chart_cfg'}, $fh ); $self->assert_matches( qr/#set labels = 1\n#set values = 2/, $$buf ); } sub test_write_chart { my $self = $_[0]; my $keep = $ENV{'KEEP_CHART'} || 0; my $parser = new Lire::ReportParser::ReportBuilder(); my $report = $parser->parsefile( dirname( __FILE__ ) . "/data/test-sqlite.xml" ); my $subreport = $report->subreport_by_id( 'top-files.0' ); $self->test_registration_file(); $self->{'chart_cfg'}->get( 'name' )->set( 'pie' ); $self->{'chart_cfg'}->get( 'title' )->set( $subreport->title() ); $self->{'chart_cfg'}->get( 'type' )->set_plugin( 'pie' ); my $pie = Lire::PluginManager->get_plugin( 'chart_type', 'pie' ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'file' ); $self->{'chart_cfg'}->type_properties()->get( 'values' )->set( 'request_total' ); my $dir = tempdir( $self->name() . '_XXXXXX', CLEANUP => !$keep ); my $chart = $pie->write_chart( $self->{'chart_cfg'}, $subreport, 'outputdir' => $dir, 'format' => 'png', ); $self->assert( -f $chart ? 1 : 0, "file '$chart' not created" ); warn( "\nChart written in: $chart\n" ) if $keep; } 1; ������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/XMLSpecParserTest.pm�������������������������������������������������������0000644�0001750�0001750�00000002452�10460672600�015701� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::XMLSpecParserTest; use strict; use base qw/ Lire::Test::TestCase tests::TestStoreFixture/; use Lire::XMLSpecParser; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'parser'} = new Lire::XMLSpecParser(); $self->set_up_test_schema(); return; } sub test_spec_start { my $self = $_[0]; $self->{'parser'}->spec_start( 'lrsml:report-spec', { 'id' => 'x-by-y', 'superservice' => 'test', 'schema' => 'test-derived', 'joined-schemas' => 'test test-extended' } ); $self->assert_isa( 'Lire::ReportSpec', $self->{'parser'}{'_spec'} ); $self->assert_str_equals( 'x-by-y', $self->{'parser'}{'_spec'}->id() ); $self->assert_str_equals( 'test', $self->{'parser'}{'_spec'}->superservice() ); $self->assert_str_equals( 'test-derived', $self->{'parser'}{'_spec'}{'schema'} ); $self->assert_deep_equals( [ 'test', 'test-extended' ], $self->{'parser'}{'_spec'}->joined_schemas() ); } 1; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/UIWidgetTest.pm������������������������������������������������������������0000644�0001750�0001750�00000004661�10460672600�014736� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::UIWidgetTest; use strict; use base qw/Lire::Test::TestCase/; use Lire::Config::TypeSpec; use Lire::Config::Value; use Curses::UI; use Lire::UI::Widget; use Lire::Test::CursesUIDriver; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'driver'} = new Lire::Test::CursesUIDriver(); $self->{'driver'}->setup_curses_ui(); $self->{'ui'} = new Curses::UI(); $self->{'driver'}->set_curses_ui( $self->{'ui'} ); $self->{'window'} = $self->{'ui'}->add( 'window', 'Window' ); $self->set_up_fake_config(); return; } sub set_up_fake_config { my $self = $_[0]; my $spec = new Lire::Config::ConfigSpec( 'name' => 'lire' ); $spec->add( new Lire::Config::StringSpec( 'name' => 'test', 'section' => 'programs', 'summary' => 'Test Summary', 'description' => '<para>Test Description</para>' ) ); $spec->add( new Lire::Config::StringSpec( 'name' => 'another_prog', 'section' => 'programs' ) ); $self->{'spec'} = $spec; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->{'driver'}->teardown_curses_ui(); return; } sub test_new { my $self = $_[0]; my $win = $self->{'window'}; $self->assert_dies( qr/missing 'value' parameter/, sub { my $widget = $win->add( 'test_widget', 'Lire::UI::Widget' ) } ); $self->assert_dies( qr/'value' parameter should be a 'Lire::Config::Value' instance, not 'HASH/, sub { my $widget = $win->add( 'test_widget', 'Lire::UI::Widget', 'value' => {} ) } ); $self->assert_dies( qr/no widget type defined for values of type 'Lire::Config::ConfigSpec'/, sub { my $widget = $win->add( 'test_widget', 'Lire::UI::Widget', 'Value' => $self->{'spec'}->instance() ) }); my $widget = $win->add( 'test_widget', 'Lire::UI::Widget', 'value' => $self->{'spec'}->get( 'another_prog' )->instance() ); $self->assert_isa( 'Lire::UI::StringWidget', $widget ); return; } 1; �������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/reports/�������������������������������������������������������������������0000755�0001750�0001750�00000000000�11677607770�013647� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/reports/test/��������������������������������������������������������������0000755�0001750�0001750�00000000000�11677607770�014626� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/reports/test/downloads-by-period.xml���������������������������������������0000644�0001750�0001750�00000002275�10460672602�021141� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE lire:report-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.0//EN" "http://www.logreport.org/LRSML/2.0/lrsml.dtd"> <lire:report-spec id="downloads-by-period" superservice="test" xmlns:lire="http://www.logreport.org/LRSML/"> <lire:title>Download by Period Report Specification</lire:title> <lire:description> <para>Test report specification using a timegroup operation and count with fields parameter. </para> </lire:description> <lire:param-spec> <lire:param name="period" type="duration"/> </lire:param-spec> <lire:display-spec> <lire:title>Download by $period Period</lire:title> </lire:display-spec> <lire:report-calc-spec> <lire:timegroup label="Period" period="$period"> <lire:count name="download_count" label="Downloads"/> <lire:count name="download_ratio" label="% Total" ratio="table"/> <lire:count name="user_count" label="Unique Users" fields="user"/> <lire:count name="user_ratio" label="% Total" ratio="table" fields="user"/> </lire:timegroup> </lire:report-calc-spec> </lire:report-spec> <!-- Keep this comment at the end of qthe file Local variables: mode: xml --> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/reports/test/top-dirs2.xml�������������������������������������������������0000644�0001750�0001750�00000002640�10460672602�017076� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE lire:report-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.1//EN" "http://www.logreport.org/LRSML/2.1/lrsml.dtd"> <lire:report-spec id="top-dirs2" superservice="test" schema="test-extended" xmlns:lire="http://www.logreport.org/LRSML/" xmlns:lrcml="http://www.logreport.org/LRCML/"> <lire:title>Top Directories Report Specification</lire:title> <lire:description> <para>Test report specification using an extended schema.</para> </lire:description> <lire:param-spec> <lire:param name="dirs_to_show" type="int" default="10"/> </lire:param-spec> <lire:display-spec> <lire:title>Downloads by Directory, Top $dirs_to_show</lire:title> </lire:display-spec> <lire:chart-configs> <lrcml:param name="chart"> <lrcml:param name="case_var" value="dirname"/> <lrcml:param name="type" value="vbars"> <lrcml:param name="y" value="bytes_total"/> </lrcml:param> </lrcml:param> </lire:chart-configs> <lire:report-calc-spec> <lire:group sort="-bytes_total dirname" limit="$dirs_to_show"> <lire:field name="dirname"/> <lire:sum name="bytes_total" label="Bytes Downloaded" field="file_size"/> <lire:sum name="bytes_ratio" label="% Total" ratio="table" field="file_size"/> </lire:group> </lire:report-calc-spec> </lire:report-spec> <!-- Keep this comment at the end of qthe file Local variables: mode: xml --> ������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/reports/test/user-downloads-utf8.xml���������������������������������������0000644�0001750�0001750�00000002136�10460672602�021105� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE lire:report-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.0//EN" "http://www.logreport.org/LRSML/2.0/lrsml.dtd"> <lire:report-spec xmlns:lire="http://www.logreport.org/LRSML/" superservice="test" id="user-downloads-utf8"> <lire:title>Tlchargement par usager</lire:title> <lire:description> <para>Ce rapport montre le nombre de fichiers tlchargs par usager.</para> </lire:description> <lire:param-spec> <lire:param name="users_to_show" type="int" default="10"/> </lire:param-spec> <lire:display-spec> <lire:title>Tlchargements par usager, Top $users_to_show </lire:title> </lire:display-spec> <lire:report-calc-spec> <lire:group sort="-request_total" limit="$users_to_show"> <lire:field name="user" label="Usager"/> <lire:count name="request_total" label="Tlchargements"/> <lire:count name="request_ratio" ratio="table" label="% Total"/> </lire:group> </lire:report-calc-spec> </lire:report-spec> <!-- Keep this comment at the end of qthe file Local variables: mode: xml End: --> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/reports/test/top-files.xml�������������������������������������������������0000644�0001750�0001750�00000002023�10460672602�017150� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE lire:report-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.0//EN" "http://www.logreport.org/LRSML/2.0/lrsml.dtd"> <lire:report-spec xmlns:lire="http://www.logreport.org/LRSML/" superservice="test" id="top-files"> <lire:title>Top Files Report Specification</lire:title> <lire:description> <para>Test report specification.</para> </lire:description> <lire:param-spec> <lire:param name="files_to_show" type="int" default="10"/> </lire:param-spec> <lire:display-spec> <lire:title>Downloads by File, Top $files_to_show</lire:title> </lire:display-spec> <lire:report-calc-spec> <lire:group sort="-request_total file" limit="$files_to_show"> <lire:field name="file"/> <lire:count name="request_total" label="Downloads"/> <lire:count name="request_ratio" ratio="table" label="% Total"/> </lire:group> </lire:report-calc-spec> </lire:report-spec> <!-- Keep this comment at the end of qthe file Local variables: mode: xml --> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/reports/test/sessions-by-length.xml����������������������������������������0000644�0001750�0001750�00000001736�10460672602�021015� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE lire:report-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.0//EN" "http://www.logreport.org/LRSML/2.0/lrsml.dtd"> <lire:report-spec id="sessions-by-length" superservice="test" schema="test-derived" xmlns:lire="http://www.logreport.org/LRSML/"> <lire:title>Sessions by Length Report Specification</lire:title> <lire:description> <para>Test report specification using a derived schema.</para> </lire:description> <lire:display-spec> <lire:title>Sessions by Length</lire:title> </lire:display-spec> <lire:report-calc-spec> <lire:rangegroup field="session_length" range-start="0" range-size="1m" label="Length"> <lire:count name="sessions_count" label="Sessions"/> <lire:count name="sessions_ratio" label="% Total" ratio="table"/> </lire:rangegroup> </lire:report-calc-spec> </lire:report-spec> <!-- Keep this comment at the end of qthe file Local variables: mode: xml --> ����������������������������������lire-2.1.1/all/lib/tests/reports/test/top-dirs.xml��������������������������������������������������0000644�0001750�0001750�00000002165�10460672602�017016� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE lire:report-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.0//EN" "http://www.logreport.org/LRSML/2.0/lrsml.dtd"> <lire:report-spec id="top-dirs" superservice="test" schema="test-extended" xmlns:lire="http://www.logreport.org/LRSML/"> <lire:title>Top Directories Report Specification</lire:title> <lire:description> <para>Test report specification using an extended schema.</para> </lire:description> <lire:param-spec> <lire:param name="dirs_to_show" type="int" default="10"/> </lire:param-spec> <lire:display-spec> <lire:title>Downloads by Directory, Top $dirs_to_show</lire:title> </lire:display-spec> <lire:report-calc-spec> <lire:group sort="-bytes_total dirname" limit="$dirs_to_show"> <lire:field name="dirname"/> <lire:sum name="bytes_total" label="Bytes Downloaded" field="file_size"/> <lire:sum name="bytes_ratio" label="% Total" ratio="table" field="file_size"/> </lire:group> </lire:report-calc-spec> </lire:report-spec> <!-- Keep this comment at the end of qthe file Local variables: mode: xml --> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/reports/test/user_downloads-report.xml�������������������������������������0000644�0001750�0001750�00000002277�10460672602�021622� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE lire:report-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.0//EN" "http://www.logreport.org/LRSML/2.0/lrsml.dtd"> <lire:report-spec id="user_downloads-report" superservice="test" xmlns:lire="http://www.logreport.org/LRSML/"> <lire:title>User's Downloads Report Specification</lire:title> <lire:description> <para>Test report specification using the min, max, first, last and records operation.</para> </lire:description> <lire:display-spec> <lire:title>User's Downloads Report</lire:title> </lire:display-spec> <lire:report-calc-spec> <lire:group sort="user"> <lire:field name="user"/> <lire:first name="first_file" field="file" sort="time_start" label="First File"/> <lire:last name="last_file" field="file" sort="time_start" label="Last File"/> <lire:min name="min_file_size" label="Smallest" field="file_size"/> <lire:max name="max_file_size" label="Largest" field="file_size"/> <lire:records fields="time_start file file_size"/> </lire:group> </lire:report-calc-spec> </lire:report-spec> <!-- Keep this comment at the end of qthe file Local variables: mode: xml --> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/reports/test/sessions-by-user_class.xml������������������������������������0000644�0001750�0001750�00000001630�10460672602�021670� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE lire:report-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.0//EN" "http://www.logreport.org/LRSML/2.0/lrsml.dtd"> <lire:report-spec id="sessions-by-user_class" superservice="test" schema="test-derived" xmlns:lire="http://www.logreport.org/LRSML/"> <lire:title>Missing Report Specification</lire:title> <lire:description> <para>This report specification uses a field which should always be <sgmltag>LIRE_NOTAVAIL</sgmltag>.</para> </lire:description> <lire:display-spec> <lire:title>Sessions by User Class</lire:title> </lire:display-spec> <lire:report-calc-spec> <lire:group> <lire:field name="user_class"/> <lire:count name="sessions_total" label="Sessions"/> </lire:group> </lire:report-calc-spec> </lire:report-spec> <!-- Keep this comment at the end of qthe file Local variables: mode: xml --> ��������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/reports/test/avg-file_size-by-timeslot.xml���������������������������������0000644�0001750�0001750�00000002000�10460672602�022233� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE lire:report-spec PUBLIC "-//LogReport.ORG//DTD Lire Report Specification Markup Language V2.0//EN" "http://www.logreport.org/LRSML/2.0/lrsml.dtd"> <lire:report-spec id="avg-file_size-by-timeslot" superservice="test" xmlns:lire="http://www.logreport.org/LRSML/"> <lire:title>Average File Size by Timeslot Report Specification</lire:title> <lire:description> <para>Test report specification for the timeslot and average operation. </para> </lire:description> <lire:param-spec> <lire:param name="unit" type="duration" default="1h"/> </lire:param-spec> <lire:display-spec> <lire:title>Average File Size By $unit Timeslot</lire:title> </lire:display-spec> <lire:report-calc-spec> <lire:timeslot label="Length" unit="$unit"> <lire:avg name="avg_file_size" field="file_size" label="Avg File Size"/> </lire:timeslot> </lire:report-calc-spec> </lire:report-spec> <!-- Keep this comment at the end of qthe file Local variables: mode: xml --> lire-2.1.1/all/lib/tests/DerivedSchemaTest.pm�������������������������������������������������������0000644�0001750�0001750�00000021207�10460672600�015753� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::DerivedSchemaTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::DlfSchema; use Lire::ExtendedSchema; use Lire::DerivedSchema; use Lire::Field; use Lire::DlfStore; use Lire::Utils qw/tempdir/; use File::Basename qw/dirname/; use Cwd qw/realpath/; sub new { my $self = shift()->SUPER::new( @_ ); $self->{'tmpdir'} = tempdir( __PACKAGE__ . "XXXXXX", 'TMPDIR' => 1, CLEANUP => 1 ); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'directory'} = realpath( dirname(__FILE__) . "/schemas" ); $self->{'old_cache'} = { %Lire::DlfSchema::SCHEMA_CACHE }; %Lire::DlfSchema::SCHEMA_CACHE = (); # Make sure the Lire::DlfSchema can find our test schemas. $self->{'cfg'}{'lr_schemas_path'} = [ $self->{'directory'} ]; $self->{'schema'} = Lire::DlfSchema::load_schema( "test-derived" ); $self->{'cfg'}{'_lr_config_spec'} = $self->lire_default_config_spec(); # We don't open the store in new() because we need to # change the configuration before $self->{'store'} = Lire::DlfStore->open( "$self->{'tmpdir'}/store", 1 ) unless defined $self->{'store'}; return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->{'store'}->_dbh()->rollback(); %Lire::DlfSchema::SCHEMA_CACHE = %{$self->{'old_cache'}}; return; } sub test_new { my $self = $_[0]; $self->assert_dies( qr/cannot find superservice in id: 'test_derived'/, sub { new Lire::DerivedSchema( 'id' => 'test_derived' ) } ); $self->assert_dies( qr/base schema cannot be an extended schema: test-extended/, sub { new Lire::DerivedSchema( 'id' => 'test-another', 'base-schema' => 'test-extended' ) } ); my $schema = new Lire::DerivedSchema( 'id' => 'test-derived', 'module' => 'MyModule', 'base-schema' => 'test', 'timestamp' => 'session_start' ); $self->assert_isa( 'Lire::DerivedSchema', $schema ); $self->assert_str_equals( 'test-derived', $schema->{'id'} ); $self->assert_str_equals( 'test', $schema->{'superservice'} ); my $base = Lire::DlfSchema::load_schema( 'test' ); $self->assert_str_equals( $base, $schema->{'base'} ); } sub test_id { my $self = $_[0]; $self->assert_isa( 'Lire::DerivedSchema', $self->{'schema'} ); $self->assert_str_equals( "test-derived", $self->{'schema'}->id() ); } sub test_superservice { my $self = $_[0]; $self->assert_isa( 'Lire::DerivedSchema', $self->{'schema'} ); $self->assert_str_equals( "test", $self->{'schema'}->superservice() ); } sub test_base { my $self = $_[0]; $self->assert_isa( 'Lire::DerivedSchema', $self->{'schema'} ); my $base = $self->{'schema'}->base(); $self->assert_isa( 'Lire::DlfSchema', $base ); $self->assert_str_equals( "test", $base->id() ); } sub test_can_join_schema { my $self = $_[0]; my $test = new Lire::DlfSchema( 'superservice' => 'test', 'timestamp' => 'time' ); $test->add_field( new Lire::Field( 'name' => 'time', 'type' => 'timestamp' ) ); $Lire::DlfSchema::SCHEMA_CACHE{'test'} = $test; my $test2 = new Lire::DlfSchema( 'superservice' => 'test2', 'timestamp' => 'time' ); $test2->add_field( new Lire::Field( 'name' => 'time', 'type' => 'timestamp' ) ); $Lire::DlfSchema::SCHEMA_CACHE{'test2'} = $test2; my $derived = new Lire::DerivedSchema( 'id' => 'test-derived', 'base-schema' => 'test', 'timestamp' => 'time', 'module' => 'MyModule' ); $derived->add_field( new Lire::Field( 'name' => 'time', 'type' => 'timestamp' ) ); $Lire::DlfSchema::SCHEMA_CACHE{'test-derived'} = $derived; my $ext1 = new Lire::ExtendedSchema( 'id' => 'test-ext1', 'base-schema' => 'test', 'module' => 'MyModule' ); my $ext2 = new Lire::ExtendedSchema( 'id' => 'test2-ext2', 'base-schema' => 'test2', 'module' => 'MyModule' ); my $ext3 = new Lire::ExtendedSchema( 'id' => 'test-ext3', 'base-schema' => 'test-derived', 'module' => 'MyModule' ); $self->assert( $derived->can_join_schema( $ext1 ) ); $self->assert( $derived->can_join_schema( $test ) ); $self->assert( $derived->can_join_schema( $ext3 ) ); $self->assert( ! $derived->can_join_schema( $derived ) ); $self->assert( ! $derived->can_join_schema( $ext2 ) ); $self->assert( ! $derived->can_join_schema( $test2 ) ); } sub test_create_sql_schema { my $self = $_[0]; $self->assert_isa( 'Lire::DerivedSchema', $self->{'schema'} ); $self->{'schema'}->create_sql_schema( $self->{'store'} ); my $sql_def = $self->{'schema'}->_sql_fields_def(); chomp $sql_def; # Trailing newline removed by SQLite my $table = $self->{'store'}->_dbh()->selectrow_hashref( "SELECT * FROM sqlite_master WHERE name = 'dlf_test-derived'" ); $self->assert_not_null( $table, "table dlf_test wasn't created" ); $self->assert_matches( qr/\Q$sql_def\E/, $table->{'sql'} ); $self->check_derived_idx(); $self->check_link_table(); $self->check_triggers(); } sub check_derived_idx { my $self = $_[0]; my $index = $self->{'store'}->_dbh()->selectrow_hashref( q{SELECT * FROM sqlite_master WHERE name = 'dlf_test-derived_session_start_idx'} ); $self->assert_not_null( $index, "index dlf_test-derived_session_start_idx wasn't created" ); $self->assert_equals( "index", $index->{'type'} ); $self->assert_equals( 'CREATE INDEX "dlf_test-derived_session_start_idx" ON "dlf_test-derived" ( session_start )', $index->{'sql'} ); } sub check_link_table { my $self = $_[0]; my $dbh = $self->{'store'}->_dbh(); my $table = $dbh->selectrow_hashref( "SELECT * FROM sqlite_master WHERE name = 'dlf_test-derived_links'" ); $self->assert_not_null( $table, "table dlf_test-derived_links wasn't created" ); $self->assert_str_equals( 'CREATE TABLE "dlf_test-derived_links" ( src_id INT, link_id INT )', $table->{'sql'} ); my $index = $dbh->selectrow_hashref( q{SELECT * FROM sqlite_master WHERE name = 'dlf_test-derived_links_src_id_idx'} ); $self->assert_not_null( $index, "index dlf_test-derived_links_src_id_idx wasn't created" ); $self->assert_str_equals( "index", $index->{'type'} ); $self->assert_str_equals( 'CREATE INDEX "dlf_test-derived_links_src_id_idx" ON "dlf_test-derived_links" ( src_id )', $index->{'sql'} ); $index = $dbh->selectrow_hashref( q{SELECT * FROM sqlite_master WHERE name = 'dlf_test-derived_links_link_id_idx'} ); $self->assert_not_null( $index, "index dlf_test-derived_links_link_id_idx wasn't created" ); $self->assert_str_equals( "index", $index->{'type'} ); $self->assert_str_equals( 'CREATE INDEX "dlf_test-derived_links_link_id_idx" ON "dlf_test-derived_links" ( link_id )', $index->{'sql'} ); } sub check_triggers { my $self = $_[0]; my $dbh = $self->{'store'}->_dbh(); my $trigger = $dbh->selectrow_hashref( q{SELECT * FROM sqlite_master WHERE name = 'dlf_test-derived_delete_trigger'} ); $self->assert_not_null( $trigger, "trigger dlf_test-derived_delete_trigger wasn't created" ); $self->assert_str_equals( "trigger", $trigger->{'type'} ); my $main_trigger_sql = <<EOS; CREATE TRIGGER "dlf_test-derived_delete_trigger" AFTER DELETE ON dlf_test BEGIN DELETE FROM "dlf_test-derived_links" WHERE src_id = old.dlf_id; END EOS chomp $main_trigger_sql; $self->assert_str_equals( $main_trigger_sql, $trigger->{'sql'} ); $trigger = $dbh->selectrow_hashref( q{SELECT * FROM sqlite_master WHERE name = 'dlf_test-derived_links_delete_trigger'} ); $self->assert_not_null( $trigger, "trigger dlf_test-derived_links_delete_trigger wasn't created" ); $self->assert_str_equals( "trigger", $trigger->{'type'} ); my $link_trigger_sql = <<EOS; CREATE TRIGGER "dlf_test-derived_links_delete_trigger" AFTER DELETE ON "dlf_test-derived" BEGIN DELETE FROM "dlf_test-derived_links" WHERE src_id = old.dlf_id; END EOS chomp $link_trigger_sql; $self->assert_str_equals( $link_trigger_sql, $trigger->{'sql'} ); } 1; �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/LrMatchTest.pm�������������������������������������������������������������0000644�0001750�0001750�00000002344�10460672577�014620� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::LrMatchTest; use strict; use base qw/Lire::Test::TestCase/; use Lire::SQLExt::LrMatch; sub test_lr_match { my $self = $_[0]; $self->assert_died( sub { Lire::SQLExt::LrMatch::lr_match( '', undef, undef ) }, qr/missing 're' parameter/ ); foreach my $test ( # Value, RE, CS, Result [ 'ANOTHER STRING', 'str', 1, 0 ], [ 'ANOTHER STRING', 'str', 0, 1 ], [ undef, 'test$', 0, 0 ], [ 'a test', 'test$', 0, 1 ], [ 'a test failing', 'test$', 0, 0 ], [ 'A 123 number', '\d+', 0, 1 ] ) { my ( $value, $re, $cs, $result ) = @$test; my @warnings = (); local $SIG{'__WARN__'} = sub { push @warnings, join( "", @_); $self->annotate( $warnings[-1] ); }; $self->assert( Lire::SQLExt::LrMatch::lr_match( $value, $re, $cs ) == $result, "lr_match( '".($value || 'undef' )."', '$re', $cs ) != $result" ); my $rx = $Lire::SQLExt::LrMatch::RE_CACHE{$re}; $self->assert_not_null( $rx, "'$re' wasn't cached" ); $self->assert( ref( $rx ) eq 'Regexp', "$rx' isn't a Regexp reference" ); $self->assert_equals( 0, scalar @warnings ); } } 1; ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lire-2.1.1/all/lib/tests/ReportParserAsciiDocBookFormatterTest.pm�����������������������������������0000644�0001750�0001750�00000010677�10460672601�022010� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package tests::ReportParserAsciiDocBookFormatterTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::ReportParser::AsciiDocBookFormatter qw/ dbk2txt /; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub _element_is_normalized { my ( $self, $element ) = @_; $self->annotate( "_element_is_normalized: $element\n" ); my $dbk_text = "<para>Wawa <$element>bobo</$element> zozo</para>"; my $e_text = <<_EOD; Wawa bobo zozo _EOD $self->assert_str_equals( $e_text, dbk2txt( $dbk_text ) ); return; } sub _test_admonition { my ( $self, $admonition ) = @_; $self->annotate( "testing admonition '$admonition'\n" ); my $dbk_text = "<$admonition><para>test</para></$admonition>"; my $uc_admonition = ucfirst( $admonition ); my $e_text = <<_EOD; $uc_admonition: test _EOD $self->assert_str_equals( $e_text, dbk2txt( $dbk_text ) ); return; } sub _test_autopcdata { my ( $self, $data ) = @_; $self->annotate( "testing autopcdata '$data'\n" ); $self->_element_is_normalized( $data ); return; } sub test_admonitions { my $self = $_[0]; my @admonitions = ( 'note', 'tip', 'important', 'caution', 'warning' ); foreach my $admonition ( @admonitions ) { $self->_test_admonition( $admonition ); } return; } sub test_all_autopcdata { my $self = $_[0]; foreach my $data ( qw/emphasis phrase trademark wordasword action application literal constant markup option optional parameter prompt property replaceable returnvalue sgmltag structfield structname symbol systemitem token type userinput varname/ ) { $self->_test_autopcdata( $data ); } return; } sub test_orderedlist { my $self = $_[0]; my $dbk_text = '<orderedlist><listitem><para>test1</para></listitem><listitem><para>test2</para></listitem></orderedlist>'; my $e_text = <<_EOD; 1. test1 2. test2 _EOD $self->assert_str_equals( $e_text, dbk2txt( $dbk_text ) ); return; } sub test_itemizedlist { my $self = $_[0]; my $dbk_text = '<itemizedlist><listitem><para>test1</para></listitem><listitem><para>test2</para></listitem></itemizedlist>'; my $e_text = <<_EOD; - test1 - test2 _EOD $self->assert_str_equals( $e_text, dbk2txt( $dbk_text ) ); return; } # varlistentry and listitem are tested here too sub test_variablelist { my $self = $_[0]; my $dbk_text = <<_EOD; <variablelist> <title>The wawa generator Report store A folder containing report data _EOD my $e_text = <<_EOD; The wawa generator Report store \t A folder containing report data _EOD $self->assert_str_equals( $e_text, dbk2txt( $dbk_text ) ); $dbk_text = <<_EOD; A folder containing report data _EOD $e_text = <<_EOD; \t A folder containing report data _EOD $self->assert_str_equals( $e_text, dbk2txt( $dbk_text ) ); return; } sub test_para { my $self = $_[0]; my $dbk_text = 'This is a very very very very very very very very very very very very very very very long paragraph'; my $e_text = <<_EOD; This is a very very very very very very very very very very very very very very very long paragraph _EOD $self->assert_str_equals( $e_text, dbk2txt( $dbk_text ) ); $self->assert_str_equals( " Test accentu.\n\n", dbk2txt( "Test accentu." ) ); return; } sub test_ulink { my $self = $_[0]; my $dbk_text = 'Go to The LogReport Foundation website.'; my $e_text = <<_EOD; Go to The LogReport Foundation (http://www.logreport.org/) website. _EOD $self->assert_str_equals( $e_text, dbk2txt( $dbk_text ) ); return; } sub test_quote { my $self = $_[0]; my $dbk_text = 'Linux'; my $e_text = <<_EOD; "Linux" _EOD $self->assert_str_equals( $e_text, dbk2txt( $dbk_text ) ); return; } 1; lire-2.1.1/all/lib/tests/ChartTypesLinesTest.pm0000644000175000017500000001206610460672577016351 00000000000000package tests::ChartTypesLinesTest; use strict; use base qw/Lire::Test::PluginTestCase/; use Lire::ChartTypes::Lines; use Lire::Config::Build qw/ac_info/; use Lire::Config::ChartSpec; use Lire::Config::ExecutableSpec; use Lire::PluginManager; use Lire::ReportParser::ReportBuilder; use Lire::Utils qw/tempdir/; use File::Basename qw/dirname/; use IO::Scalar; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'cfg'}{'ploticus_path'} = new Lire::Config::ExecutableSpec( 'name' => 'ploticus_path' )->instance( 'value' => ac_info( 'PLOTICUS' ) ); $self->{'cfg'}{'lr_chart_font'} = ''; $self->{'chart_cfg'} = new Lire::Config::ChartSpec( 'name' => 'chart' )->instance(); return; } sub create_plugin { return new Lire::ChartTypes::Lines(); } sub properties_spec_file { return dirname( __FILE__ ) . "/../Lire/ChartTypes/ct_lines.xml"; } sub registration_file { return dirname( __FILE__ ) . "/../Lire/ChartTypes/ct_lines_init"; } sub set_up_subreport { my $self = $_[0]; my $parser = new Lire::ReportParser::ReportBuilder(); my $report = $parser->parsefile( dirname( __FILE__ ) . "/data/test-sqlite.xml" ); $self->{'subreport'} = $report->subreport_by_id( 'top-files.0' ); } sub test_get_vars { my $self = $_[0]; $self->set_up_subreport(); $self->test_registration_file(); my $info = $self->{'subreport'}->table_info(); $info->set_variables_indices(); $self->{'chart_cfg'}->get( 'type' )->set_plugin( 'lines' ); my $lines = Lire::PluginManager->get_plugin( 'chart_type', 'lines' ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'file' ); my $props = $self->{'chart_cfg'}->get( 'type' )->get_properties(); $props->get( 'y' )->set( 'request_total' ); $self->assert_deep_equals( [$info->column_info_by_name( 'request_total' )], $lines->get_vars( $self->{'chart_cfg'} ) ); $props->get( 'x' )->set( 'request_ratio' ); $self->assert_deep_equals( [$info->column_info_by_name( 'request_ratio' ), $info->column_info_by_name( 'request_total' )], $lines->get_vars( $self->{'chart_cfg'} ) ); $props->get( 'y2' )->set( 'request_ratio' ); $self->assert_deep_equals( [$info->column_info_by_name( 'request_ratio' ), $info->column_info_by_name( 'request_total' ), $info->column_info_by_name( 'request_ratio' )], $lines->get_vars( $self->{'chart_cfg'} ) ); } sub test_write_parameters { my $self = $_[0]; $self->set_up_subreport(); my $fh = new IO::Scalar(); my $buf = $fh->sref(); $self->test_registration_file(); my $info = $self->{'subreport'}->table_info(); $info->set_variables_indices(); $self->{'chart_cfg'}->get( 'type' )->set_plugin( 'lines' ); my $lines = Lire::PluginManager->get_plugin( 'chart_type', 'lines' ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'file' ); my $props = $self->{'chart_cfg'}->get( 'type' )->get_properties(); $props->get( 'y' )->set( 'request_total' ); $lines->write_parameters( $self->{'chart_cfg'}, $fh ); my @lines = split /\n/, $$buf; $self->assert_str_equals( '#set x = 1', $lines[0] ); $self->assert_str_equals( '#set cats = yes', $lines[-4] ); $self->assert_str_equals( '#set stubvert = yes', $lines[-3] ); $self->assert_str_equals( '#set legend = max+0.1 max', $lines[-2] ); $self->assert_str_equals( '#set y = 2', $lines[-1] ); $$buf = ''; $props->get( 'x' )->set( 'request_ratio' ); $props->get( 'y2' )->set( 'request_ratio' ); $props->get( 'numbers' )->set( 1 ); $lines->write_parameters( $self->{'chart_cfg'}, $fh ); @lines = split /\n/, $$buf; $self->assert_str_equals( '#set cats = no', $lines[-5] ); $self->assert_str_equals( '#set x = 2', $lines[-4] ); $self->assert_str_equals( '#set y = 3', $lines[-3] ); $self->assert_str_equals( '#set y2 = 4', $lines[-2] ); $self->assert_str_equals( '#set numbers = yes', $lines[-1] ); } sub test_write_chart { my $self = $_[0]; $self->set_up_subreport(); my $keep = $ENV{'KEEP_CHART'} || 0; $self->test_registration_file(); $self->{'chart_cfg'}->get( 'name' )->set( 'lines' ); $self->{'chart_cfg'}->get( 'title' )->set( $self->{'subreport'}->title() ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'file' ); $self->{'chart_cfg'}->get( 'type' )->set_plugin( 'lines' ); my $props = $self->{'chart_cfg'}->get( 'type' )->get_properties(); $props->get( 'y' )->set( 'request_total' ); $props->get( 'numbers' )->set( 1 ); my $lines = Lire::PluginManager->get_plugin( 'chart_type', 'lines' ); my $dir = tempdir( $self->name() . '_XXXXXX', CLEANUP => !$keep ); my $chart = $lines->write_chart( $self->{'chart_cfg'}, $self->{'subreport'}, 'outputdir' => $dir, 'format' => 'png' ); $self->assert( -f $chart ? 1 : 0, "file '$chart' not created" ); warn( "\nChart written in: $chart\n" ) if $keep; } 1; lire-2.1.1/all/lib/tests/ReportGroupTest.pm0000644000175000017500000002377610460672577015572 00000000000000package tests::ReportGroupTest; use strict; use base qw/Lire::Test::TestCase/; use Lire::Report::Group; use Lire::Report::TableInfo; sub set_up { my $self = shift->SUPER::set_up(); $self->set_up_nested2_info(); return $self; } sub tear_down { my $self = shift->SUPER::tear_down(); return $self; } sub set_up_nested2_info { my $self = $_[0]; my $table_info = new Lire::Report::TableInfo(); $table_info->create_column_info( 'cell1', 'categorical', 'string' ); my $group_info1 = $table_info->create_group_info( 'nested1' ); $group_info1->create_column_info( 'cell2', 'categorical', 'string' ); $group_info1->create_column_info( 'cell3', 'numerical', 'int' ); my $group_info2 = $table_info->create_group_info( 'nested2' ); $group_info2->create_column_info( 'cell4', 'categorical', 'string' ); $group_info2->create_column_info( 'cell5', 'numerical', 'int' ); $self->{'nested2_info'} = $table_info; return; } sub set_up_group { my $self = $_[0]; my $top = new Lire::Report::Group( bless( {}, "Lire::Report::Entry" ), $self->{'nested2_info'} ); # cell1, cell2, $cell3, $cell4, $cell5 my $report_data = [ [ '1x1', [[ '1x21', 131 ], [ "1x22", 132 ]], [[ '1x41', 151]]], [ '2x1', [[ '2x21', 231]], [[ '2x41', 251 ], [ '2x42', 252 ]]], [ '3x1', [[ '3x21', 331], [ '3x22', 332]], [[ '3x41', 351 ], [ '3x42', 352 ]]], ]; $self->{'entry_dlf_keys'} = {}; $self->{'entries'} = {}; foreach my $row ( @$report_data ) { my $dlf_t = {}; my $entry = $top->create_entry(); $dlf_t->{ 'cell1'} = $row->[0]; $entry->add_name( $row->[0] ); $self->{'entry_dlf_keys'}{$row->[0]} = {%$dlf_t}; $self->{'entries'}{$row->[0]} = $entry; my $nested1 = $entry->create_group(); foreach my $n1 ( @{$row->[1]} ) { my $e = $nested1->create_entry(); $dlf_t->{ 'cell2'} = $n1->[0]; $dlf_t->{ 'cell3'} = $n1->[1]; $self->{'entry_dlf_keys'}{$n1->[0]} = {%$dlf_t}; $self->{'entries'}{$n1->[0]} = $e; $e->add_name( 'Cell ' . $n1->[0], $n1->[0] ); $e->add_value( 'value' => $n1->[1], 'content' => $n1->[0] ); } my $nested2 = $entry->create_group(); foreach my $n2 ( @{$row->[2]} ) { my $e = $nested2->create_entry(); $dlf_t->{ 'cell4'} = $n2->[0]; $dlf_t->{ 'cell5'} = $n2->[1]; $self->{'entry_dlf_keys'}{$n2->[0]} = {%$dlf_t}; $self->{'entries'}{$n2->[0]} = $e; $e->add_name( 'Cell ' . $n2->[0], $n2->[0] ); $e->add_value( 'value' => $n2->[1], 'content' => $n2->[0] ); } } $self->{'group'} = $top; return; } sub test_assign_row_indices { my $self = $_[0]; my $table_info = $self->{'nested2_info'}; my $group = new Lire::Report::Group( bless( {}, 'Lire::Report::Entry' ), $table_info ); foreach my $row ( 1 .. 10) { my $entry = $group->create_entry(); $entry->add_name( "row$row" ); my $group1 = $entry->create_group(); $group1->show( 2 ); my $group2 = $entry->create_group(); foreach my $gidx ( 1..5 ) { my $n_entry1 = $group1->create_entry(); $n_entry1->add_name( 'row' . $row . 'group1-' . $gidx ); $n_entry1->add_value( 'content' => 10 ); my $n_entry2 = $group2->create_entry(); $n_entry2->add_name( 'row' . $row . 'group2-' . $gidx ); $n_entry2->add_value( 'content' => 5 ); } } my $idx = $group->assign_row_indices( 1 ); $self->assert_equals( 1, $group->row_idx() ); $self->assert_equals( 61, $idx ); my $row_idx = 2; foreach my $entry ( $group->entries() ) { $self->assert_equals( $row_idx, $entry->row_idx() ); $self->assert_equals( $row_idx, $entry->data_by_name( 'nested1')->row_idx() ); my @subentries = $entry->data_by_name( 'nested1')->entries(); $self->assert_equals( $row_idx + 1, $subentries[0]->row_idx() ); $self->assert_equals( $row_idx + 2, $subentries[1]->row_idx() ); foreach my $idx ( 2 .. 4) { $self->assert_null( $subentries[$idx]->row_idx(), "row_idx() should return undef" ); } my $offset = 1; $self->assert_equals( $row_idx, $entry->data_by_name( 'nested2')->row_idx() ); foreach my $sub ( $entry->data_by_name( 'nested2')->entries() ) { $self->assert_equals( $row_idx + $offset++, $sub->row_idx() ); } $row_idx += $offset; } return; } sub test_compute_column_info_stats { my $self = $_[0]; my $table_info = new Lire::Report::TableInfo(); $table_info->create_column_info( 'cell1', 'categorical', 'string', "Length0000000016" ); my $group_info1 = $table_info->create_group_info( 'nested1' ); $group_info1->create_column_info( 'cell2', 'categorical', 'string', 'Length0010' ); $group_info1->create_column_info( 'cell3', 'numerical', 'int', 'Length7'); my $subreport = new Lire::Report::Group( bless( {}, 'Lire::Report::Entry' ), $table_info ); $subreport->show( 2 ); $subreport->set_summary_value( 'cell3', 'content' => 'Length7', value => 0 ); foreach ( 1..10 ) { my $e = $subreport->create_entry(); $e->add_name( 'Len4' ); my $group = $e->create_group(); $group->set_summary_value( 'cell3', 'content' => 'Length000012', 'value' => 0 ); foreach ( 1..5) { my $sub = $group->create_entry(); $sub->add_name( 'Length7' ); $sub->add_value( 'content' => 'Length7', value => 0 ); } } $subreport->assign_row_indices( -1 ); $subreport->compute_column_info_stats(); $self->assert_equals( 16, $subreport->group_info()->column_info_by_name( 'cell1' )->max_chars() ); $self->assert_equals( 8, $subreport->group_info()->column_info_by_name( 'cell1' )->avg_chars() ); $self->assert_equals( 10, $subreport->group_info()->column_info_by_name( 'cell2' )->max_chars() ); $self->assert_equals( 8, $subreport->group_info()->column_info_by_name( 'cell2' )->avg_chars() ); $self->assert_equals( 12, $subreport->group_info()->column_info_by_name( 'cell3' )->max_chars() ); $self->assert_equals( 8, $subreport->group_info()->column_info_by_name( 'cell3' )->avg_chars() ); return; } sub test_new { my $self = $_[0]; my $entry = bless {}, 'Lire::Report::Entry'; my $info = new Lire::Report::TableInfo(); $self->assert_died( sub { new Lire::Report::Group() }, qr/missing \'entry\' parameter/); $self->assert_died( sub { new Lire::Report::Group( {}, $info ) }, qr/\'entry\' parameter should be a \'Lire::Report::Entry\' instance, not \'HASH/ ); $self->assert_died( sub { new Lire::Report::Group( $entry ) }, qr/missing \'group_info\' parameter/ ); $self->assert_died( sub { new Lire::Report::Group( $entry, {} ) }, qr/\'group_info\' parameter should be a \'Lire::Report::GroupInfo\' instance, not \'HASH/ ); my $group = new Lire::Report::Group( $entry, $info ); $self->assert_not_null( $group, 'new() returned undef' ); $self->assert_isa( 'Lire::Report::Group', $group ); $self->assert_equals( 'group', $group->{'type'} ); $self->assert_deep_equals( [], $group->{'entries'} ); $self->assert_deep_equals( {}, $group->{'summary'} ); $self->assert_equals( 0, $group->{'nrecords'} ); $self->assert_equals( 0, $group->{'missing_cases'} ); $self->assert_null( $group->{'show'}, "'show' attribute should be undef" ); $self->assert_equals( $entry, $group->{'parent_entry'} ); $self->assert_equals( $info, $group->{'group_info'} ); $self->assert_null( $group->{'row_idx'}, "'row_idx' attribute should be undef" ); return; } sub test_create_entry { my $self = $_[0]; my $group = new Lire::Report::Group( bless( {}, 'Lire::Report::Entry' ), new Lire::Report::TableInfo ); my $entry = $group->create_entry(); $self->assert_not_null( $entry, "create_entry() returned undef" ); $self->assert( UNIVERSAL::isa( $entry, 'Lire::Report::Entry'), "create_entry() should return an instance of Lire::Report::Entry: $entry" ); $self->assert_deep_equals( [ $entry ], $group->{'entries'} ); my $entry2 = $group->create_entry(); $self->assert_deep_equals( [ $entry, $entry2 ], $group->{'entries'} ); return; } sub test_find_entry { my $self = $_[0]; $self->set_up_group(); my $group = $self->{'group'}; $self->assert_null( $self->{'group'}->find_entry( {} ), "find_entry() should return undef"); $self->assert_null( $self->{'group'}->find_entry( { 'cell1' => 'blah' } ), "find_entry() should return undef"); foreach my $key ( keys %{$self->{'entry_dlf_keys'}}) { my $dlf_key = $self->{'entry_dlf_keys'}{$key}; my $e_entry = $self->{'entries'}{$key}; my $name = $e_entry->group_info()->name(); my $entry = $group->find_entry( $name, $dlf_key ); $self->assert_not_null( $entry, sprintf( "find_entry( '$name', '$key' ) with dlf cell1=%s, cell2=%s, cell4=%s returned undef", map { defined $_ ? $_ : 'undef' } @{$dlf_key}{'cell1','cell2','cell4'} )); $self->assert_equals( $e_entry, $entry ); } return; } 1; lire-2.1.1/all/lib/tests/ChartTypesScatTest.pm0000644000175000017500000001040310460672577016162 00000000000000package tests::ChartTypesScatTest; use strict; use base qw/Lire::Test::PluginTestCase/; use Lire::ChartTypes::Scat; use Lire::Config::Build qw/ac_info/; use Lire::Config::ChartSpec; use Lire::Config::ExecutableSpec; use Lire::PluginManager; use Lire::ReportParser::ReportBuilder; use Lire::Utils qw/tempdir/; use File::Basename qw/dirname/; use IO::Scalar; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'cfg'}{'ploticus_path'} = new Lire::Config::ExecutableSpec( 'name' => 'ploticus_path' )->instance( 'value' => ac_info( 'PLOTICUS' ) ); $self->{'cfg'}{'lr_chart_font'} = ''; $self->{'chart_cfg'} = new Lire::Config::ChartSpec( 'name' => 'chart' )->instance(); return; } sub create_plugin { return new Lire::ChartTypes::Scat(); } sub properties_spec_file { return dirname( __FILE__ ) . "/../Lire/ChartTypes/ct_scat.xml"; } sub registration_file { return dirname( __FILE__ ) . "/../Lire/ChartTypes/ct_scat_init"; } sub set_up_subreport { my $self = $_[0]; my $parser = new Lire::ReportParser::ReportBuilder(); my $report = $parser->parsefile( dirname( __FILE__ ) . "/data/test-sqlite.xml" ); $self->{'subreport'} = $report->subreport_by_id( 'downloads-by-period.0' ); } sub test_get_vars { my $self = $_[0]; $self->set_up_subreport(); $self->test_registration_file(); my $scat = Lire::PluginManager->get_plugin( 'chart_type', 'scat' ); my $info = $self->{'subreport'}->table_info(); $info->set_variables_indices(); $self->{'chart_cfg'}->type( $scat ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'timegroup:time_start' ); my $props = $self->{'chart_cfg'}->type_properties(); $props->get( 'x' )->set( 'user_count' ); $props->get( 'y' )->set( 'download_count' ); $self->assert_deep_equals( [$info->column_info_by_name( 'user_count' ), $info->column_info_by_name( 'download_count' ), ], $scat->get_vars( $self->{'chart_cfg'} ) ); } sub test_write_parameters { my $self = $_[0]; $self->set_up_subreport(); my $fh = new IO::Scalar(); my $buf = $fh->sref(); $self->test_registration_file(); my $info = $self->{'subreport'}->table_info(); $info->set_variables_indices(); my $scat = Lire::PluginManager->get_plugin( 'chart_type', 'scat' ); $self->{'chart_cfg'}->type( $scat ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'timegroup:time_start' ); my $props = $self->{'chart_cfg'}->type_properties(); $props->get( 'x' )->set( 'user_count' ); $props->get( 'y' )->set( 'download_count' ); $scat->write_parameters( $self->{'chart_cfg'}, $fh ); $self->assert_str_equals( $$buf, <{'chart_cfg'}->title( 'My Title' ); $self->{'chart_cfg'}->xlabel( '# Users' ); $self->{'chart_cfg'}->ylabel( '# Downloads' ); $props->get( 'corr' )->set( 1 ); $props->get( 'label' )->set( 1 ); $$buf = ''; $scat->write_parameters( $self->{'chart_cfg'}, $fh ); $self->assert_str_equals( $$buf, <set_up_subreport(); my $keep = $ENV{'KEEP_CHART'} || 0; $self->test_registration_file(); my $scat = Lire::PluginManager->get_plugin( 'chart_type', 'scat' ); $self->{'chart_cfg'}->basename( 'scat' ); $self->{'chart_cfg'}->get( 'case_var' )->set( 'timegroup:time_start' ); $self->{'chart_cfg'}->type( $scat ); my $props = $self->{'chart_cfg'}->type_properties(); $props->get( 'x' )->set( 'user_count' ); $props->get( 'y' )->set( 'download_count' ); $props->get( 'corr' )->set( 1 ); $props->get( 'label' )->set( 1 ); my $dir = tempdir( $self->name() . '_XXXXXX', CLEANUP => !$keep ); my $chart = $scat->write_chart( $self->{'chart_cfg'}, $self->{'subreport'}, 'outputdir' => $dir, 'format' => 'png' ); $self->assert( -f $chart ? 1 : 0, "file '$chart' not created" ); warn( "\nChart written in: $chart\n" ) if $keep; } 1; lire-2.1.1/all/lib/tests/ConfigPluginTest.pm0000644000175000017500000001462210460672577015654 00000000000000package tests::ConfigPluginTest; use strict; use Lire::Config::TypeSpec; use Lire::Config::Plugin; use IO::Scalar; use tests::ConfigValuesTest; use base qw/tests::ConfigValueTest/; sub new { my $self = shift->SUPER::new( @_ ); $self->{'spec'} = new Lire::Config::ConfigSpec(); $self->{'plugin_spec'} = new Lire::Config::PluginSpec( 'name' => 'plugin' ); $self->{'spec'}->add( $self->{'plugin_spec'} ); foreach my $name ( qw/option_1 option_2 option_3/ ) { my $opt = new Lire::Config::OptionSpec( 'name' => $name ); $self->{'plugin_spec'}->add( $opt ) ; } my $option_1 = new Lire::Config::RecordSpec( 'name' => 'option_1_properties' ); $option_1->add( new Lire::Config::StringSpec( 'name' => 'string1' ) ); $self->{'spec'}->add( $option_1 ); my $option_2 = new Lire::Config::RecordSpec( 'name' => 'option_2_properties' ); $option_2->add( new Lire::Config::StringSpec( 'name' => 'string2' ) ); $option_2->add( new Lire::Config::IntegerSpec( 'name' => 'int' ) ); $self->{'spec'}->add( $option_2 ); return $self; } sub set_up { my $self = shift; $self->SUPER::set_up( @_ ); $self->{'cfg'}{'_lr_config_spec'} = $self->{'spec'}; $self->{'plugin'} = new Lire::Config::Plugin( 'spec' => $self->{'plugin_spec'} ); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub type { return "Lire::Config::Plugin"; } sub spec { return $_[0]{'plugin_spec'}; } sub test_new { my $self = $_[0]; $self->SUPER::test_new(); my $empty_dict = new Lire::Config::RecordSpec( 'name' => $self->{'plugin_spec'}->name() . "_no_properties" ); $self->assert_null( $self->{'plugin'}{'_plugin'}, '_plugin non-null' ); $self->assert_deep_equals( $empty_dict->instance(), $self->{'plugin'}->{'_properties'} ); my $plugin = $self->{'plugin_spec'}->instance( 'value' => 'option_1' ); $self->assert_str_equals( 'option_1', $plugin->{'_plugin'} ); $self->assert_deep_equals( $plugin, $plugin->new() ); my $other = $plugin->new( 'value' => 'option_2' ); $self->assert_str_equals( 'option_2', $other->{'_plugin'} ); } sub test_set_plugin { my $self = $_[0]; $self->{'plugin'}->set_plugin( 'option_1' ); $self->assert_str_equals( 'option_1', $self->{'plugin'}{'_plugin'} ); my $option_1_props = $self->{'spec'}->get( 'option_1_properties' ); $self->assert_deep_equals( $option_1_props->instance(), $self->{'plugin'}{'_properties'} ); my $old_props = $self->{'plugin'}{'_properties'}; $self->{'plugin'}->set_plugin( 'option_1' ); $self->assert_str_equals( $old_props, $self->{'plugin'}{'_properties'} ); $self->{'plugin'}->set_plugin( 'option_2' ); $self->assert_str_equals( 'option_2', $self->{'plugin'}{'_plugin'} ); my $option_2_props = $self->{'spec'}->get( 'option_2_properties' ); $self->assert_deep_equals( $option_2_props->instance(), $self->{'plugin'}{'_properties'} ); $self->{'plugin'}->set_plugin( 'option_3' ); $self->assert_str_equals( 'option_3', $self->{'plugin'}{'_plugin'} ); $self->assert_deep_equals( $self->{'plugin'}->spec()->get_properties_spec( undef )->instance(), $self->{'plugin'}{'_properties'} ); } sub test_as_value { my $self = $_[0]; local $SIG{'__WARN__'} = sub { $self->annotate( join "", $@ ) }; my $plugin = $self->{'plugin'}; $self->assert_deep_equals( { 'plugin' => undef, 'properties' => {}, }, $plugin->as_value(), ); $plugin->set_plugin( 'option_1' ); $self->assert_deep_equals( { 'plugin' => 'option_1', 'properties' => { 'string1' => '' }, }, $plugin->as_value(), ); } sub test_save_xml { my $self = $_[0]; $self->{'plugin'}->set_plugin( 'option_1' ); $self->check_save_xml_default( $self->{'plugin'}->clone() ); $self->check_save_xml_obsolete( $self->{'plugin'}->clone() ); $self->{'plugin'}->get( 'string1' )->set( 'test' ); my $fh = new IO::Scalar(); $self->{'plugin'}->save_xml( $fh, 0 ); my $buf = $fh->sref(); $self->assert_equals( < test EOXML $self->{'plugin'}->set_plugin( 'option_3' ); $$buf = ''; $self->{'plugin'}->save_xml( $fh, 1 ); $self->assert_equals( < EOXML $self->{'plugin'}{'_plugin'} = undef; $fh = new IO::Scalar(); $self->{'plugin'}->save_xml( $fh, 1 ); $buf = $fh->sref(); $self->assert_str_equals( '', $$buf ); } sub test_has_properties { my $self = $_[0]; my $plugin = $self->{'plugin'}; $plugin->set_plugin( 'option_1' ); $self->assert( $plugin->has_properties(), 'option_1 *does not* have properties!' ); $plugin->set_plugin( 'option_3' ); $self->assert( ! $plugin->has_properties(), 'option_3 *has* properties!' ); $plugin->set_plugin( 'option_2' ); $self->assert( $plugin->has_properties(), 'option_2 *does not* have properties!' ); } sub test_is_equals { my $self = $_[0]; $self->SUPER::test_is_equals(); my $plugin = $self->{'plugin'}; my $option = $self->{'spec'}->get( 'option_2_properties' )->get( 'string2' )->instance( 'value' => 'A string' ); my $other = $plugin->clone(); $plugin->set_plugin( 'option_2' ); $plugin->set( $option ); $self->assert( ! $plugin->is_equals( $other ), '! is_equals()' ); $other->set_plugin( 'option_2' ); $self->assert( ! $plugin->is_equals( $other ), '! is_equals()' ); $other->set( $option->clone() ); $self->assert( $plugin->is_equals( $other ), 'is_equals()' ); } sub test_is_valid { my $self = $_[0]; my $plugin = $self->{'plugin'}; $self->assert( !$plugin->is_valid(), '!is_valid()' ); $plugin->set_plugin( 'option_3' ); $self->assert( $plugin->is_valid(), 'is_valid()' ); $plugin->set_plugin( 'option_2' ); $self->assert( !$plugin->is_valid(), '!is_valid()' ); $plugin->get( 'int' )->set( 10 ); $self->assert( $plugin->is_valid(), 'is_valid()' ); } 1; lire-2.1.1/all/lib/tests/ConfigReportSectionSpecTest.pm0000644000175000017500000000414210460672577020025 00000000000000package tests::ConfigReportSectionSpecTest; use strict; use tests::ConfigSpecTest; use base qw/tests::ConfigTypeSpecBase/; use Lire::Config::ReportSectionSpec; sub new { my $self = shift->SUPER::new( @_ ); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub type { return 'Lire::Config::ReportSectionSpec'; } sub test_new { my $self = $_[0]; $self->SUPER::test_new(); my $spec = new Lire::Config::ReportSectionSpec( 'name' => 'section' ); $self->assert_str_equals( 'Lire::ReportSection', $spec->class() ); $self->assert_str_equals( 'title', $spec->label_component() ); my $components = [ $spec->components() ]; $self->assert_num_equals( 4, scalar @$components ); $self->assert_isa( 'Lire::Config::StringSpec', $components->[0] ); $self->assert_str_equals( 'title', $components->[0]->name() ); $self->assert_not_null( $components->[0]->summary() ); $self->assert_not_null( $components->[0]->text_description() ); $self->assert_isa( 'Lire::Config::DlfSchemaSpec', $components->[1] ); $self->assert_str_equals( 'superservice', $components->[1]->name() ); $self->assert_num_equals( 1, $components->[1]->superservices() ); $self->assert_not_null( $components->[1]->summary() ); $self->assert_not_null( $components->[1]->text_description() ); $self->assert_isa( 'Lire::Config::XMLSpecListSpec', $components->[2] ); $self->assert_str_equals( 'filters', $components->[2]->name() ); $self->assert_str_equals( 'filters', $components->[2]->type() ); $self->assert_not_null( $components->[2]->summary() ); $self->assert_not_null( $components->[2]->text_description() ); $self->assert_isa( 'Lire::Config::XMLSpecListSpec', $components->[3] ); $self->assert_str_equals( 'specs', $components->[3]->name() ); $self->assert_str_equals( 'reports', $components->[3]->type() ); $self->assert_not_null( $components->[3]->summary() ); $self->assert_not_null( $components->[3]->text_description() ); } 1; lire-2.1.1/all/lib/tests/ReportChartConfigTest.pm0000644000175000017500000000265410460672601016641 00000000000000package tests::ReportChartConfigTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::Config::TypeSpec; use Lire::ChartType; use Lire::Report::ChartConfig; use Lire::PluginManager; use Lire::Test::Mock; sub new { my $self = shift->SUPER::new( @_ ); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->set_up_plugin_mgr(); $self->{'scatterplot'} = new_proxy Lire::Test::Mock( 'Lire::ChartType' ); $self->{'scatterplot'}->set_result( 'name' => 'scatterplot' ); Lire::PluginManager->register_plugin( $self->{'scatterplot'} ); $self->{'cfg'}{'_lr_config_spec'} = new Lire::Config::ConfigSpec(); return $self; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return $self; } sub test_new { my $self = $_[0]; my $chart = new Lire::Report::ChartConfig(); $self->assert_isa( 'Lire::Report::ChartConfig', $chart ); $self->assert_isa( 'Lire::Config::ChartSpec', $chart->spec() ); $self->assert_dies( qr/\'spec\' parameter should be a \'Lire::Config::ChartSpec\' instance/, sub { new Lire::Report::ChartConfig( 'spec' => new Lire::Config::StringSpec( 'name' => 'test' ) ) } ); } sub test_type { my $self = $_[0]; my $chart = new Lire::Report::ChartConfig(); $chart->get( 'type' )->set_plugin( 'scatterplot' ); $self->assert_str_equals( $self->{'scatterplot'}, $chart->type() ); } 1; lire-2.1.1/all/lib/tests/OldDlfAdapterTest.pm0000644000175000017500000000700010460672577015725 00000000000000package tests::OldDlfAdapterTest; use strict; use base qw/ tests::DlfConverterProcessFixture /; use vars qw/$converter_script/; use Lire::OldDlfAdapter; use Lire::DlfConverterProcess; use File::Basename qw/dirname/; use Cwd qw/realpath/; use Lire::Utils qw/tempdir create_file/; BEGIN { $converter_script = realpath( dirname(__FILE__) . '/helpers' ) . '/oldconverter2dlf'; chmod 0755, $converter_script; }; sub schema_fixtures { return { 'message' => < EOF }; } sub import_job_fixtures { return { 'test' => < { 'line_count' => 4, 'error_count' => 1, 'dlf_count' => 3, 'ignored_count' => 0, 'saved_count' => 0, 'dlf' => { 'message' => [ { 'dlf_id' => 1, 'dlf_source' => 'myjob-20041202', 'ts' => 1030000000, 'ipaddr' => "127.0.0.1", 'host' => "localhost", 'message' => "Test", 'status' => undef, }, { 'dlf_id' => 2, 'dlf_source' => 'myjob-20041202', 'ts' => 1030000100, 'host' => undef, 'ipaddr' => "192.168.1.1", 'message' => "Ping", 'status' => undef, }, { 'dlf_id' => 3, 'dlf_source' => 'myjob-20041202', 'ts' => 1030000200, 'host' => "host.test.com", 'ipaddr' => undef, 'message' => "This_is_a_msg.", 'status' => undef, }, ], }, }, ); sub converter_fixtures { return [ new Lire::OldDlfAdapter( "message", $converter_script ), ]; } sub test_old_conversion { my $self = $_[0]; local $ENV{'OldDlfAdapterTest'} = join( ":", @{Lire::Config->get( 'lr_schemas_path' )}); my $p = $self->create_dlf_converter_process( "test", "oldconverter" ); $p->{'_job_id'} = 'myjob-20041202'; $p->run_import_job(); $self->assert_dlf_converter_match_results( $results{'test'}, $p ); } sub test_new { my $self = $_[0]; $self->assert_dies( qr/missing \'schema\' parameter/, sub { new Lire::OldDlfAdapter() } ); $self->assert_dies( qr/invalid schema name:/, sub { new Lire::OldDlfAdapter( 'unknown', $converter_script ) }); $self->assert_dies( qr/missing \'script\' parameter/, sub { new Lire::OldDlfAdapter( 'message' ) } ); my $tmpdir = tempdir( "old_dlf_adapter_XXXXXX", 'CLEANUP' => 1 ); create_file( $tmpdir . "oldconverter" ); $self->assert_dies( qr/script is not executable: \'/, sub { new Lire::OldDlfAdapter( 'message', "$tmpdir/old_dlf_adapter" ) } ); my $adapter = new Lire::OldDlfAdapter( "message", $converter_script ); $self->assert_isa( 'Lire::OldDlfAdapter', $adapter ); $self->assert_str_equals( 'oldconverter', $adapter->name() ); $self->assert_str_equals( $converter_script, $adapter->script() ); $self->assert_str_equals( "message", $adapter->schemas() ); } 1; lire-2.1.1/all/lib/tests/GroupFieldTest.pm0000644000175000017500000001026510460672600015312 00000000000000package tests::GroupFieldTest; use strict; use base qw/Lire::Test::TestCase tests::TestStoreFixture/; use Lire::GroupField; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); $self->init_i18n(); return $self; } sub set_up { my $self = shift->SUPER::set_up(); $self->set_up_locale(); $self->set_up_test_schema(); my $spec = new Lire::ReportSpec(); $spec->superservice( 'test' ); $self->{'i18n_groupfield'} = new Lire::GroupField( 'name' => 'file', 'report_spec' => $spec, 'i18n_domain' => 'lire-test', 'label' => 'JPEG Files' ); return $self; } sub tear_down { my $self = shift->SUPER::tear_down(); $self->tear_down_locale(); return $self; } sub test_new { my $self = $_[0]; my $spec = new Lire::ReportSpec(); $spec->superservice( 'test' ); my $group_field = new Lire::GroupField( 'name' => 'file', 'report_spec' => $spec, 'label' => 'JPEG Files' ); $self->assert_not_null( $group_field, "new() returned undef" ); $self->assert( UNIVERSAL::isa( $group_field, 'Lire::GroupField' ), 'new() returned something other than a Lire::GroupField instance' ); $self->assert_died( sub { new Lire::GroupField() }, qr/missing \'name\' parameter/, ); $self->assert_died( sub { new Lire::GroupField( 'name' => 'tata toto' ) }, qr/invalid \'name\' parameter: /, ); $self->assert_died( sub { new Lire::GroupField( 'name' => 'file') }, qr/missing \'report_spec\' parameter/, ); $self->assert_died( sub { new Lire::GroupField( 'name' => 'file', 'report_spec' => {} ) }, qr/\'report_spec\' parameter should be a \'Lire::ReportSpec\' instance, not \'HASH/, ); $self->assert_died( sub { new Lire::GroupField( 'name' => 'wawa', 'report_spec' => $spec, 'label' => 'wawalabel' ) }, qr/'wawa' field name is not defined in the specification's schemas/, ); $self->assert_died( sub { new Lire::GroupField( 'name' => 'file_size', 'report_spec' => $spec, 'label' => 'wawalabel' ) }, qr/'file_size' field is of type 'bytes'. Use Lire::Rangegroup for this type/, ); $self->assert_died( sub { new Lire::GroupField( 'name' => 'time_start', 'report_spec' => $spec, 'label' => 'wawalabel' ) }, qr/'time_start' field is of type 'timestamp'. Use Lire::Timeslot or Lire::Timegroup for this type/, ); $self->assert_str_equals( 'file', $group_field->{'name'} ); $self->assert_str_equals( 'JPEG Files', $group_field->{'label'} ); $self->assert_str_equals( 'lire', $group_field->{'i18n_domain'} ); } sub test_Lire::GroupField::label_i18n { my $self = $_[0]; my $group_field = $self->{'i18n_groupfield'}; $self->assert_str_equals( 'JPEG Files', $group_field->label() ); $self->set_locale( 'fr_CA.iso8859-1' ); $self->assert_str_equals( 'Fichiers JPEG', $group_field->label() ); $group_field->{'label'} = 'Downloads'; $self->assert_str_equals( 'Tlchargements', $group_field->label() ); } sub test_label_nolabel_i18n { my $self = $_[0]; my $group_field = $self->{'i18n_groupfield'}; delete $group_field->{'label'}; $self->assert_str_equals( 'File', $group_field->label() ); $self->set_locale( 'fr_CA.iso8859-1' ); $self->assert_str_equals( 'Fichier', $group_field->label() ); } 1; lire-2.1.1/all/lib/tests/OutputFormatsHTMLTest.pm0000644000175000017500000001117610460672601016576 00000000000000package tests::OutputFormatsHTMLTest; use strict; use base qw/Lire::Test::PluginTestCase/; use Lire::OutputFormats::HTML; use Lire::PluginManager; use Lire::Utils qw/tempdir create_file/; use File::Basename qw/dirname/; use File::Path qw/rmtree /; use Lire::Test::Mock; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'testdir'} = dirname( __FILE__ ) ; $self->{'tmpdir'} = tempdir( $self->name() . '_XXXXXX' ); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); Lire::Test::Mock->reset_factories(); rmtree( $self->{'tmpdir'} ); return; } sub create_plugin { return new Lire::OutputFormats::HTML(); } sub properties_spec_file { return dirname( __FILE__ ) . "/../Lire/OutputFormats/of_html.xml"; } sub registration_file { return dirname( __FILE__ ) . "/../Lire/OutputFormats/of_html_init"; } sub test_format_report { my $self = $_[0]; $self->test_registration_file(); Lire::Test::Mock->set_mock_factory( 'Lire::ReportParser::HTMLWriter', 'write_report' => '' ); my $html = Lire::PluginManager->get_plugin( 'output_format', 'html' ); $html->format_report( "$self->{'testdir'}/data/test-sqlite.xml", $self->{'tmpdir'}, { 'one_page' => 0, 'xhtml' => 0 } ); my ($writer) = @{Lire::Test::Mock->mock_instances( 'Lire::ReportParser::HTMLWriter' )}; my ( $ob, $report, $dir, %args ) = @{$writer->get_invocation( 'write_report' )}; $self->assert_isa( 'Lire::Report', $report ); $self->assert_str_equals( $self->{'tmpdir'}, $dir ); $self->assert_num_equals( 0, $args{'xhtml'} ); $self->assert_num_equals( 0, $args{'one_page'} ); } sub test_mime_report { my $self = $_[0]; my $page = <A link EOPAGE $self->test_registration_file(); my %args = (); Lire::Test::Mock->set_mock_factory( 'Lire::ReportParser::HTMLWriter', 'write_report' => sub { my $dir = $_[2]; %args = @_[3..$#_]; create_file( "$dir/index.html", $page ); create_file( "$dir/chart1.jpg" ); create_file( "$dir/chart2.png" ); create_file( "$dir/lire.css" ); create_file( "$dir/lire.png" ); } ); my $html = Lire::PluginManager->get_plugin( 'output_format', 'html' ); my $entity = $html->mime_report( "$self->{'testdir'}/data/test-sqlite.xml" ); $self->assert_num_equals( 1, $args{'one_page'} ); $self->assert_isa( 'MIME::Entity', $entity); $self->assert_str_equals( 'multipart/related', $entity->head()->mime_type() ); $self->assert_num_equals( 5, scalar $entity->parts() ); my $part = $entity->parts(0); $self->assert_str_equals( 'text/html', $part->head()->mime_type() ); $self->assert_str_equals( "quoted-printable\n", $part->head()->get( 'content-transfer-encoding' ) ); $self->assert_str_equals( 'utf-8', $part->head()->mime_attr( 'content-type.charset' ) ); $self->assert_str_equals( <bodyhandle()->as_string() ); A link EOF $part = $entity->parts(1); $self->assert_str_equals( 'image/jpeg', $part->head()->mime_type() ); $self->assert_str_equals( "\n", $part->head()->get( 'content-id' ) ); $self->assert_str_equals( "base64\n", $part->head()->get( 'content-transfer-encoding' ) ); $part = $entity->parts(2); $self->assert_str_equals( 'image/png', $part->head()->mime_type() ); $self->assert_str_equals( "\n", $part->head()->get( 'content-id' ) ); $self->assert_str_equals( "base64\n", $part->head()->get( 'content-transfer-encoding' ) ); $part = $entity->parts(3); $self->assert_str_equals( 'text/css', $part->head()->mime_type() ); $self->assert_str_equals( "\n", $part->head()->get( 'content-id' ) ); $self->assert_str_equals( "quoted-printable\n", $part->head()->get( 'content-transfer-encoding' ) ); } 1; lire-2.1.1/all/lib/tests/ui.pm0000644000175000017500000000077710460672601013037 00000000000000package tests::ui; use File::Basename qw/dirname/; use Cwd qw/realpath/; use base 'Test::Unit::TestSuite'; sub name { 'All UI Lire Unit Tests' } sub include_tests { # Files containing test cases all ends in Test.pm my $dir = realpath( dirname(__FILE__) ); opendir DIR, $dir or die "can't opendir $dir: $!"; my @tests = (); foreach my $e ( readdir DIR ) { next unless $e =~ /^(UI.*Test)\.pm$/; push @tests, "tests::$1"; } closedir DIR; @tests; } 1; lire-2.1.1/all/lib/tests/UIBoolWidgetTest.pm0000644000175000017500000000604710460672600015552 00000000000000package tests::UIBoolWidgetTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::Config::TypeSpec; use Curses::UI; use Lire::Test::CursesUIDriver; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'driver'} = new Lire::Test::CursesUIDriver(); $self->{'driver'}->setup_curses_ui(); $self->{'ui'} = new Curses::UI(); $self->{'driver'}->set_curses_ui( $self->{'ui'} ); $self->{'window'} = $self->{'ui'}->add( 'window', 'Window' ); my $spec = new Lire::Config::ConfigSpec( 'name' => 'lire' ); $spec->add( new Lire::Config::BooleanSpec( 'name' => 'test' ) ); $self->{'bool_value'} = $spec->get( 'test' )->instance( 'value' => 1 ); $self->{'spec'} = $spec; return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->{'driver'}->teardown_curses_ui(); return; } sub test_new { my $self = $_[0]; my $win = $self->{'window'}; $self->assert_dies( qr{missing 'value' parameter}, sub { my $widget = $win->add( 'test_widget', 'Lire::UI::BoolWidget' ) }); $self->assert_dies( qr{'value' parameter should be a 'Lire::Config::Scalar' instance, not 'HASH}, sub { my $widget = $win->add( 'test_widget', 'Lire::UI::BoolWidget', 'Value' => {} ) }); my $widget = $win->add( 'test_widget', 'Lire::UI::BoolWidget', 'value' => $self->{'bool_value'} ); $self->assert_isa( 'Lire::UI::BoolWidget', $widget ); $self->assert_str_equals( \&Lire::UI::BoolWidget::_on_change_cb, $widget->{'-onchange'} ); $self->assert_deep_equals( [ 'yes', 'no' ], $widget->{'-values'} ); $self->assert_str_equals( 0, $widget->{'-selected'} ); return; } sub test_refresh_view { my $self = $_[0]; my $widget = $self->{'window'}->add( 'test_widget', 'Lire::UI::BoolWidget', 'value' => $self->{'bool_value'} ); $self->{'bool_value'}->set( 'false' ); $widget->refresh_view(); $self->assert_num_equals( 1, $widget->{'-selected'} ); $self->{'bool_value'}->set( 'true' ); $widget->refresh_view(); $self->assert_num_equals( 0, $widget->{'-selected'} ); } sub test_on_change_cb { my $self = $_[0]; my $called = 'onvaluechanged not called'; my $win = $self->{'window'}; my $widget = $win->add( 'test_widget', 'Lire::UI::BoolWidget', 'value' => $self->{'bool_value'}, 'onvaluechanged' => sub { $called = 'called' } ); $widget->{'-selected'} = 1; Lire::UI::BoolWidget::_on_change_cb( $widget ); $self->assert( ! $self->{'bool_value'}->as_value(), "! as_value()" ); $widget->{'-selected'} = 0; Lire::UI::BoolWidget::_on_change_cb( $widget ); $self->assert( $self->{'bool_value'}->as_value(), "as_value()" ); $self->assert_str_equals( 'called', $called ); } 1; lire-2.1.1/all/lib/tests/LrFirstTest.pm0000644000175000017500000001175010460672601014640 00000000000000package tests::LrFirstTest; use strict; use base qw/Lire::Test::TestCase/; use Lire::SQLExt::LrFirst; sub set_up { my $self = shift()->SUPER::set_up(); $self->{'lr_first'} = new Lire::SQLExt::LrFirst(); $self->{'lr_first_key'} = new Lire::SQLExt::LrFirst( 'key' ); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub test_new { my $self = $_[0]; $self->assert_null( $self->{'lr_first'}{'_value'}, '_value should be undefined' ); $self->assert_deep_equals( [], $self->{'lr_first'}{'_sort_values'} ); $self->assert_deep_equals( [], $self->{'lr_first'}{'_sort_str'} ); $self->assert_equals( 'value', $self->{'lr_first'}{'_return'} ); $self->assert_equals( 'key', $self->{'lr_first_key'}{'_return'} ); $self->assert_deep_equals( $self->{'lr_first'}, $self->{'lr_first'}->new() ); $self->assert_deep_equals( $self->{'lr_first_key'}, $self->{'lr_first_key'}->new() ); } sub test_is_number { my $self = $_[0]; my @tests = ( [ 0, 1 ], [ '0', 1 ], [ 0xFF, 1 ], [ 'abcde', 0 ], [ '0astring', 0 ], [ '0xFF', 0 ] ); foreach my $t ( @tests ) { if ( $t->[1] ) { $self->assert( Lire::SQLExt::LrFirst::is_number( $t->[0] ), "is_number( $t->[0] ) should be true" ); } else { $self->assert( ! Lire::SQLExt::LrFirst::is_number( $t->[0] ), "is_number( $t->[0] ) should be false" ); } } } sub test_step_nosortkeys { my $self = $_[0]; my $aggr = $self->{'lr_first'}; $aggr->step( undef ); $self->assert_null( $aggr->{'_value'}, 'value should be undef' ); $aggr->step( 'abcde' ); $self->assert_equals( 'abcde', $aggr->{'_value'} ); $aggr->step( '0123' ); $self->assert_equals( 'abcde', $aggr->{'_value'} ); } sub test_step { my $self = $_[0]; my $aggr = $self->{'lr_first'}; $aggr->step( undef, 'host1', 10 ); $self->assert_null( $aggr->{'_value'}, "'_value' attribute should be undef" ); $aggr->step( 'user1', undef, 10 ); $self->assert_null( $aggr->{'_value'}, "'_value' attribute should be undef" ); $aggr->step( 'user1', 'host1', 'user1' ); $self->assert_equals( 'user1', $aggr->{'_value'} ); $self->assert_deep_equals( [ 1, 1 ], $aggr->{'_sort_str'} ); $self->assert_deep_equals( [ 'host1', 'user1' ], $aggr->{'_sort_values'} ); $aggr->step( 'user1', undef, 'user1' ); $self->assert_equals( 'user1', $aggr->{'_value'} ); $self->assert_deep_equals( [ 1, 1 ], $aggr->{'_sort_str'} ); $self->assert_deep_equals( [ 'host1', 'user1' ], $aggr->{'_sort_values'} ); $aggr->step( 'user2', 'host1', 'abcde' ); $self->assert_equals( 'user2', $aggr->{'_value'} ); $self->assert_deep_equals( [ 1, 1 ], $aggr->{'_sort_str'} ); $self->assert_deep_equals( [ 'host1', 'abcde' ], $aggr->{'_sort_values'} ); $aggr->step( 'user3', 'ahost', 'user1' ); $self->assert_equals( 'user3', $aggr->{'_value'} ); $self->assert_deep_equals( [ 1, 1 ], $aggr->{'_sort_str'} ); $self->assert_deep_equals( [ 'ahost', 'user1' ], $aggr->{'_sort_values'} ); $aggr->step( 'user5', 'ahost', 10 ); $self->assert_equals( 'user5', $aggr->{'_value'} ); $self->assert_deep_equals( [ 1, 1 ], $aggr->{'_sort_str'} ); $self->assert_deep_equals( [ 'ahost', '10' ], $aggr->{'_sort_values'} ); } sub test_step_num { my $self = $_[0]; my $aggr = $self->{'lr_first'}; $aggr->step( 'user1', 'host1', '1024' ); $self->assert_equals( 'user1', $aggr->{'_value'} ); $self->assert_deep_equals( [ 1, 0 ], $aggr->{'_sort_str'} ); $self->assert_deep_equals( [ 'host1', 1024 ], $aggr->{'_sort_values'} ); $aggr->step( 'user0', 'host1', '512' ); $self->assert_equals( 'user0', $aggr->{'_value'} ); $self->assert_deep_equals( [ 1, 0 ], $aggr->{'_sort_str'} ); $self->assert_deep_equals( [ 'host1', 512 ], $aggr->{'_sort_values'} ); $aggr->step( 'usera', 'host1', '0a512' ); $self->assert_equals( 'usera', $aggr->{'_value'} ); $self->assert_deep_equals( [ 1, 1 ], $aggr->{'_sort_str'} ); $self->assert_deep_equals( [ 'host1', '0a512' ], $aggr->{'_sort_values'} ); $aggr->step( 'userb', 'host1', '0512' ); $self->assert_equals( 'userb', $aggr->{'_value'} ); $self->assert_deep_equals( [ 1, 1 ], $aggr->{'_sort_str'} ); $self->assert_deep_equals( [ 'host1', '0512' ], $aggr->{'_sort_values'} ); } sub test_finalize { my $self = $_[0]; $self->{'lr_first'}{'_value'} = 10; $self->assert_num_equals( 10, $self->{'lr_first'}->finalize() ); $self->{'lr_first_key'}{'_sort_values'} = [ 'test', 'test1']; $self->assert_str_equals( 'test test1', $self->{'lr_first_key'}->finalize() ); $self->{'lr_first_key'}{'_sort_values'} = []; $self->assert_str_equals( '', $self->{'lr_first_key'}->finalize() ); } 1; lire-2.1.1/all/lib/tests/functional.pm0000644000175000017500000000104510460672601014551 00000000000000package tests::functional; use File::Basename qw/dirname/; use Cwd qw/realpath/; use base 'Test::Unit::TestSuite'; sub name { "All Lire's Functional Tests" } sub include_tests { # Files containing test cases all ends in Test.pm my $dir = realpath( dirname(__FILE__) . "/functional" ); opendir DIR, $dir or die "can't opendir $dir: $!"; my @tests = (); foreach my $e ( readdir DIR ) { next unless $e =~ /(.*Test)\.pm$/; push @tests, "tests::functional::$1"; } closedir DIR; @tests; } 1; lire-2.1.1/all/lib/tests/AggregatorTest.pm0000644000175000017500000002657310460672577015362 00000000000000package tests::AggregatorTest; use strict; use base qw/ Lire::Test::TestCase tests::TestStoreFixture /; use Lire::ReportSpec; use Lire::Report::Subreport; use Lire::Report::TableInfo; use Lire::Test::Mock; use tests::MockAggregate; use tests::MockAggregator; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->set_up_test_store(); my $spec = $self->{'spec'} = new Lire::ReportSpec(); $spec->superservice( 'test' ); $spec->joined_schemas( [ 'test-extended' ] ); $self->{'aggregator'} = new tests::MockAggregator( 'report_spec' => $spec ); $spec->calc_spec( $self->{'aggregator'} ); my $nested1 = new tests::MockAggregator( 'name' => 'nested1', 'report_spec' => $spec, 'parent' => $self->{'aggregator'} ); my $nested2 = new tests::MockAggregator( 'name' => 'nested2', 'report_spec' => $spec, 'parent' => $self->{'aggregator'} ); $self->{'aggregator'}->ops( [ $nested1, $nested2 ] ); $nested1->ops( [ new tests::MockAggregate( 'name' => 'mock1', 'parent' => $nested1, 'report_spec' => $spec ) ] ); $nested2->ops( [ new tests::MockAggregate( 'name' => 'mock2', 'parent' => $nested2, 'report_spec' => $spec ) ] ); return; } sub set_up_mock_query_spec { my $self = $_[0]; my $top = new_proxy Lire::Test::Mock( 'tests::MockAggregator', 'report_spec' => $self->{'spec'} ); $top->set_result( 'create_entry' => sub { my ($self, $group, $row ) = @_; return undef if ($self->{'count'} || 0) > 3; my $e = $group->create_entry(); $e->add_name( $row->{'client_host'} ); $e->add_name( $row->{'user'} ); $self->{'count'}++; return $e; } ); my $nested1 = new_proxy Lire::Test::Mock( 'tests::MockAggregator', 'report_spec' => $self->{'spec'}, 'parent' => $top, 'name' => 'nested1' ); $nested1->set_result( 'create_entry' => sub { my ($self, $group, $row ) = @_; my $e = $group->create_entry(); $e->add_name( $row->{'connection_id'} ); return $e; } ); $top->ops( [ $nested1 ] ); $nested1->ops( [ new tests::MockAggregate( 'name' => 'mock', 'parent' => $nested1, 'report_spec' => $self->{'spec'} ) ] ); $self->{'spec'}->calc_spec( $top ); $self->{'mock_query_spec'} = $top; return; } sub set_up_mock_query { my $self = $_[0]; $self->{'mock_query_info'} = new Lire::Report::TableInfo(); $self->{'mock_query_info'}->create_column_info( 'client_host', 'categorical', 'string' ); $self->{'mock_query_info'}->create_column_info( 'user', 'categorical', 'string' ); my $n1_info = $self->{'mock_query_info'}->create_group_info( 'nested1' ); $n1_info->create_column_info( 'connection_id', 'categorical', 'string' ); $n1_info->create_column_info( 'mock', 'numerical', 'int' ); $self->{'mock_query'} = new Lire::DlfQuery( 'test' ); $self->{'mock_query'}->add_group_field( 'client_host' ); $self->{'mock_query'}->add_group_field( 'user' ); $self->{'mock_query'}->set_sort_spec( 'client_host user' ); my $nested1 = $self->{'mock_query'}->create_nested_query(); $nested1->add_group_field( 'connection_id' ); $nested1->set_sort_spec( 'connection_id' ); $nested1->add_aggr_field( '_lr_nrecords', 'count()' ); $nested1->add_aggr_field( 'mock', 'count()' ); return; } sub set_up_mock_query_report { my $self = $_[0]; my $stream = $self->{'store'}->open_dlf_stream( 'test', 'r' ); my $subreport = new Lire::Report::Subreport( 'mock', 'mock-subreport' ); $subreport->table_info( $self->{'mock_query_info'} ); $subreport->nrecords( 24 ); $subreport->set_summary_value( 'mock', 'content' => 24 ); my %group_cache = (); foreach my $c ( [ '127.0.0.1', 'francis', '13', '13' ], [ '192.168.250.1', 'flacoste', '2', '2' ], [ '192.168.250.2', 'joostvb', '5', '5' ], [ '192.168.250.3', 'wdankers', '3', '3' ], ) { my $entry = $subreport->create_entry(); $entry->add_name( $c->[0] ); $entry->add_name( $c->[1] ); my $group = $entry->create_group(); $group->nrecords( $c->[2] ); $group->set_summary_value( 'mock', 'content' => $c->[3] ); $group_cache{$c->[0] . $c->[1]} = $group; } my %n_group_cache = (); foreach my $c ( [ '127.0.0.1', 'francis', 'AABBCCDD', '13', '13' ], [ '192.168.250.1', 'flacoste', 'AABBCCDE', '1', '1' ], [ '192.168.250.1', 'flacoste', 'AABBCCDF', '1', '1' ], [ '192.168.250.2', 'joostvb', 'AABBCCDG', '5', '5' ], [ '192.168.250.3', 'wdankers', 'AABBCCDD', '3', '3' ], ) { my $group = $group_cache{ $c->[0] . $c->[1]}; my $entry = $group->create_entry(); $entry->add_name( $c->[2] ); $entry->add_value( 'content' => $c->[4] ); } $self->{'mock_query_subreport'} = $subreport; return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->tear_down_test_store(); return; } sub test_create_entries { my $self = $_[0]; $self->set_up_mock_query(); $self->set_up_mock_query_report(); my $aggr = new_proxy Lire::Test::Mock( 'tests::MockAggregator', 'report_spec' => $self->{'spec'} ); $aggr->set_result( 'build_table' => '' ); my $filter = new Lire::Test::Mock( 'Lire::FilterExpr', 'sql_expr' => 'myfilter = ?', 'sql_params' => [ 'myparam' ] ); $self->{'spec'}->filter_spec( $filter ); my $subreport = new Lire::Report::Subreport( 'mock', 'mock-subreport' ); $subreport->table_info( $self->{'mock_query_info'} ); $aggr->create_entries( $subreport ); $self->assert_equals( 0, scalar $subreport->entries() ); $aggr->{'store'} = $self->{'store'}; $aggr->create_entries( $subreport ); $self->assert_num_equals( 1, $aggr->invocation_count( 'build_table' ) ); $self->assert_num_equals( $self->{'store'}, $aggr->get_invocation( 'build_table' )->[1] ); my $query = $aggr->get_invocation( 'build_table' )->[2]; $self->assert_isa( 'Lire::DlfQuery', $query ); $self->assert_str_equals( 'test', $query->stream_name() ); $self->assert_deep_equals( [ 'test', 'test-extended' ], $query->joined_streams() ); $self->assert_str_equals( 'myfilter = ?', $query->filter_clause() ); $self->assert_deep_equals( [ 'myparam' ], $query->sql_params() ); } sub test_build_query { my $self = $_[0]; my $test_query = new Lire::DlfQuery( "test" ); my $sub1 = $test_query->create_nested_query(); $sub1->add_aggr_field( '_lr_nrecords', 'count(*)' ); $sub1->add_aggr_field( 'mock1', 'count()' ); my $sub2 = $test_query->create_nested_query(); $sub2->add_aggr_field( '_lr_nrecords', 'count(*)' ); $sub2->add_aggr_field( 'mock2', 'count()' ); my $query = new Lire::DlfQuery( "test" ); $self->{'aggregator'}->build_query( $query ); $self->assert_deep_equals( $test_query, $query ); } sub test_build_table_summary { my $self = $_[0]; my $query = new Lire::DlfQuery( "test" ); $self->{'aggregator'}->build_query( $query ); my $subreport = new Lire::Report::Subreport( 'mock', 'mock-subreport' ); $subreport->table_info( $self->{'spec'}->create_table_info() ); $self->{'aggregator'}->build_table_summary( $self->{'store'}, $query, $subreport ); $self->assert_equals( 24, $subreport->nrecords() ); $self->assert_equals( 24, $subreport->get_summary_value( 'mock1' )->{'content'} ); $self->assert_equals( 24, $subreport->get_summary_value( 'mock2' )->{'content'} ); } sub test_set_group_summary { my $self = $_[0]; my $query = new Lire::DlfQuery( "test" ); $self->{'aggregator'}->build_query( $query ); my $stream = $self->{'store'}->open_dlf_stream( 'test', 'r' ); my $subreport = new Lire::Report::Subreport( 'mock', 'mock-subreport' ); my $aggr1 = $self->{'aggregator'}->ops()->[0]->ops()->[0]; $subreport->table_info( $self->{'spec'}->create_table_info() ); $self->{'aggregator'}->set_group_summary( $subreport, { '_lr_nrecords' => 24, 'mock1' => 22, 'mock2' => 23, } ); $self->assert_equals( 24, $subreport->nrecords() ); $self->assert_equals( 22, $subreport->get_summary_value( 'mock1' )->{'content'} ); $self->assert_equals( 23, $subreport->get_summary_value( 'mock2' )->{'content'} ); $self->assert_equals( 1, scalar @{$aggr1->{'parent_groups'}}); $self->assert_str_equals( $subreport, $aggr1->{'parent_groups'}[0] ); my $nested1 = $self->{'aggregator'}->ops()->[0]; my $entry = $subreport->create_entry(); $entry->add_name(); my $group = $entry->create_group(); $nested1->set_group_summary( $group, { '_lr_nrecords' => 24, 'mock1' => 22, 'mock2' => 23, } ); $self->assert_equals( 2, scalar @{$aggr1->{'parent_groups'}}); $self->assert_str_equals( $subreport, $aggr1->{'parent_groups'}[1] ); } sub test_build_table { my $self = $_[0]; $self->set_up_mock_query_spec(); $self->set_up_mock_query(); $self->set_up_mock_query_report(); my $e_subreport = $self->{'mock_query_subreport'}; my $subreport = new Lire::Report::Subreport( 'mock', 'mock-subreport' ); $subreport->table_info( $self->{'mock_query_info'} ); $self->{'mock_query_spec'}->build_table( $self->{'store'}, $self->{'mock_query'}, $subreport ); $self->assert_deep_equals( $e_subreport, $subreport ); } sub test_is_name_defined { my $self = $_[0]; my $aggr = $self->{'aggregator'}; $aggr->{'name'} = 'topAggr'; $self->assert( $aggr->is_name_defined( 'topAggr' ), 'is_name_defined( "topAggr" ) returned false' ); $self->assert( $aggr->is_name_defined( 'nested1' ), 'is_name_defined( "nested1" ) returned false' ); $self->assert( !$aggr->is_name_defined( 'newName' ), 'is_name_defined( "newName" ) returned true' ); } 1; lire-2.1.1/all/lib/tests/UIFileWidgetTest.pm0000644000175000017500000001376710460672600015545 00000000000000package tests::UIFileWidgetTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::Config::TypeSpec; use Lire::Test::CursesUIDriver; use Curses::UI; use File::Basename qw/ dirname basename /; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'driver'} = new Lire::Test::CursesUIDriver(); $self->{'driver'}->setup_curses_ui(); $self->{'ui'} = new Curses::UI(); $self->{'driver'}->set_curses_ui( $self->{'ui'} ); $self->{'window'} = $self->{'ui'}->add( 'window', 'Window' ); my $spec = new Lire::Config::ConfigSpec(); $spec->add( new Lire::Config::FileSpec( 'name' => 'file_param' ) ); $self->{'file_param'} = $spec->get( 'file_param' )->instance( 'value' => '/etc/passwd' ); $self->{'spec'} = $spec; return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->{'driver'}->teardown_curses_ui(); return; } sub test_new { my $self = $_[0]; my $win = $self->{'window'}; $self->assert_dies( qr{missing 'value' parameter}, sub { my $widget = $win->add( 'file_widget', 'Lire::UI::FileWidget' ) } ); $self->assert_dies( qr{'value' parameter should be a 'Lire::Config::Scalar' instance, not 'HASH}, sub { my $widget = $win->add( 'file_widget', 'Lire::UI::FileWidget', 'Value' => {} ) } ); my $refresh_widget = undef; no warnings 'redefine'; local *Lire::UI::FileWidget::_refresh_warn_label = sub { $refresh_widget = shift }; my $widget = $win->add( 'file_widget', 'Lire::UI::FileWidget', 'value' => $self->{'file_param'} ); $self->assert_isa( 'Lire::UI::FileWidget', $widget ); my $file_field = $widget->getobj( 'file_field' ); $self->assert_isa( 'Curses::UI::TextEntry', $file_field ); $self->assert_str_equals( '/etc/passwd', $file_field->text() ); $self->assert_str_equals( \&Lire::UI::FileWidget::_on_change_cb, $file_field->{'-onchange'} ); $self->assert_str_equals( $widget, $refresh_widget, "'_refresh_warn_label' wasn't called" ); my $warn_label = $widget->getobj( 'warn_label' ); $self->assert_isa( 'Curses::UI::Label', $warn_label ); $self->assert_str_equals( '', $warn_label->{'-text'} ); my $browse_btn = $widget->getobj( 'browse_btn' ); $self->assert_isa( 'Curses::UI::Buttonbox', $browse_btn ); $self->assert_str_equals( '[Browse]', $browse_btn->{'-buttons'}[0]{'-label'} ); $self->assert_str_equals( \&Lire::UI::FileWidget::_browse_cb, $browse_btn->{'-buttons'}[0]{'-onpress'} ); return; } sub test_refresh_view { my $self = $_[0]; my $widget = $self->{'window'}->add( 'test_widget', 'Lire::UI::FileWidget', 'value' => $self->{'file_param'} ); my $file_field = $widget->getobj( 'file_field' ); my $warn_label = $widget->getobj( 'warn_label' ); $self->{'file_param'}->set( '/etc/group' ); $widget->refresh_view(); $self->assert_str_equals( '/etc/group', $file_field->text() ); $self->assert_str_equals( '', $warn_label->text() ); $self->{'file_param'}->set( '/no/such/file' ); $widget->refresh_view(); $self->assert_str_equals( '/no/such/file', $file_field->text() ); $self->assert_str_equals( 'Invalid filename', $warn_label->text() ); } sub test_on_change_cb { my $self = $_[0]; my $called = 'onvaluechanged not called'; my $win = $self->{'window'}; my $widget = $win->add( 'test_widget', 'Lire::UI::FileWidget', 'value' => $self->{'file_param'}, 'onvaluechanged' => sub { $called = 'called' } ); my $file_field = $widget->getobj( 'file_field' ); my $or_value = $file_field->text(); $file_field->text( '/etc/group' ); Lire::UI::FileWidget::_on_change_cb( $file_field ); $self->assert_str_not_equals( $or_value, $self->{'file_param'}->get() ); $self->assert_str_equals( '/etc/group', $self->{'file_param'}->get() ); $self->assert_str_equals( 'called', $called ); $file_field->text( '/no_such_file' ); Lire::UI::FileWidget::_on_change_cb( $file_field ); $self->assert_str_equals( '/no_such_file', $self->{'file_param'}->get() ); my $warn_label = $widget->getobj( 'warn_label' ); $self->assert_str_equals( 'Invalid filename', $warn_label->{'-text'} ); $file_field->text( '/etc/passwd' ); Lire::UI::FileWidget::_on_change_cb( $file_field ); $self->assert_str_equals( '', $warn_label->{'-text'} ); return; } sub test_browse_cb { my $self = $_[0]; my $dlg = '< undef >'; my $filename = $self->{'file_param'}->get(); $self->{'driver'}->add_event_loop_handler( sub { $dlg = $_[1]; $self->assert_str_equals( dirname( $filename ), $dlg->{'-path'} ); $self->assert_str_equals( basename( $filename ), $dlg->{'-file'} ); $dlg->getobj('pathvalue')->text( '/dev' ); $dlg->getobj('filevalue')->text( 'null' ); $dlg->getobj('buttons')->{'-selected'} = 0; } ); my $widget = $self->{'window'}->add( 'test_widget', 'Lire::UI::FileWidget', 'value' => $self->{'file_param'} ); Lire::UI::FileWidget::_browse_cb( $widget->getobj( 'browse_btn' ) ); $self->assert_isa( 'Curses::UI::Dialog::Filebrowser', $dlg ); $self->assert_str_equals( '/dev/null', $self->{'file_param'}->get() ); $self->{'driver'}->add_event_loop_handler( sub { $dlg = $_[1]; $dlg->getobj('pathvalue')->text( '/dev' ); $dlg->getobj('filevalue')->text( 'zero' ); $dlg->getobj('buttons')->{'-selected'} = 1; } ); Lire::UI::FileWidget::_browse_cb( $widget->getobj( 'browse_btn' ) ); $self->assert_str_equals( '/dev/null', $self->{'file_param'}->get() ); } 1; lire-2.1.1/all/lib/tests/ReportParserLaTeXWriterTest.pm0000644000175000017500000004644410460672601020006 00000000000000package tests::ReportParserLaTeXWriterTest; use strict; use base qw/Lire::Test::TestCase tests::TestStoreFixture tests::ChartTypesFixture /; use Lire::ReportParser::LaTeXWriter; use Lire::ReportParser::ReportBuilder; use Lire::Utils qw/tempdir create_file file_content/; use File::Path qw/rmtree/; use Lire::Config::ConfigSpec; use Lire::DlfSchema; use Lire::Field; use Lire::Report; use Lire::Report::Section; use Lire::Report::Subreport; use Lire::Report::TableInfo; use Lire::Report::ChartConfig; use Lire::ChartType; use Lire::PluginManager; use Lire::Test::Mock; use IO::Scalar; use Time::Local; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'tmpdir'} = tempdir( $self->name() . "_XXXXXX" ); $self->{'writer'} = new_proxy Lire::Test::Mock( 'Lire::ReportParser::LaTeXWriter' ); $self->{'writer'}{'_fh'} = new IO::Scalar(); $self->{'keep_tmpdir'} = 0; return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); rmtree( $self->{'tmpdir'}, 0 ) unless $self->{'keep_tmpdir'}; return; } sub test_write_report { my $self = $_[0]; my $report = new Lire::Report(); $report->add_section( new Lire::Report::Section( 'Section 1' ) ); $report->add_section( new Lire::Report::Section( 'Section 2' ) ); create_file( "$self->{'tmpdir'}/font.tex", '' ); $self->{'writer'}->set_result( 'write_header', '' ); $self->{'writer'}->set_result( 'write_titlepage', '' ); $self->{'writer'}->set_result( 'write_section', '' ); $self->{'writer'}->set_result( 'write_appendix', '' ); $self->{'writer'}->set_result( 'process_latex', '' ); $self->{'writer'}{'_fh'} = undef; $self->{'writer'}->write_report( $report, "$self->{'tmpdir'}/report.pdf", 'pdf', "$self->{'tmpdir'}/font.tex" ); $self->assert_str_equals( 'pdf', $self->{'writer'}{'_format'} ); $self->assert_str_equals( "$self->{'tmpdir'}/report.pdf", $self->{'writer'}{'_outputfile'}, ); $self->assert_str_equals( $self->{'tmpdir'}, $self->{'writer'}{'_outputdir'} ); $self->assert_str_equals( "$self->{'tmpdir'}/report", $self->{'writer'}{'_outputbase'}, ); $self->assert_str_equals( "$self->{'tmpdir'}/font.tex", $self->{'writer'}{'_preamble'}, ); $self->assert_not_null( $self->{'writer'}{'_fh'}, "missing _fh attribute" ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_header' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_titlepage' ) ); $self->assert_num_equals( 2, $self->{'writer'}->invocation_count( 'write_section' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_appendix' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'process_latex' ) ); } sub test_write_header { my $self = $_[0]; $self->{'cfg'}{'unicode.tex'} = '/usr/share/lire/tex/unicode.tex'; $self->{'writer'}{'_preamble'} = 'font.tex'; $self->{'writer'}{'_format'} = 'pdf'; $self->{'writer'}->write_header(); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->assert_str_equals( <title( '{My report}' ); my $start = timelocal( 0, 0, 0, 1, 0, 2004 ); my $time = timelocal( 15, 15, 3, 2, 0, 2004 ); $report->timespan_start( $start ); $report->timespan_end( $start + 86400); $report->date( $time ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_titlepage( $report ); $self->assert_str_equals( <<'EOF', $$buf ); \title{\{My report\}} \author{} \date{Report for 2004-01-01 00:00 -- 2004-01-02 00:00\\ Report generated 2004-01-02 03:15} \maketitle \tableofcontents EOF } sub test_write_section { my $self = $_[0]; my $section = new Lire::Report::Section( '{Section title}' ); $section->description( 'Section description' ); my $sub1 = new Lire::Report::Subreport( 'test', 'test1' ); $sub1->id( 'test-test1' ); $section->add_subreport( $sub1 ); my $sub2 = new_missing Lire::Report::Subreport( 'test', 'test2', 'No good reason' ); $sub2->id( 'test-test2' ); $section->add_subreport( $sub2 ); $self->{'writer'}->set_result( 'write_subreport', '' ); $self->{'writer'}->set_result( 'write_missing_subreport', '' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_section( $section ); $self->assert_str_equals( <<'EOF', $$buf ); \chapter{\{Section title\}} Section description EOF $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_subreport' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_missing_subreport' ) ); } sub test_write_missing_subreport { my $self = $_[0]; my $sub = new_missing Lire::Report::Subreport( 'test', 'test1', '{No good reason}' ); $sub->title( '{My subreport}' ); $sub->description( 'Description' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_missing_subreport( $sub ); $self->assert_str_equals( <<'EOF', $$buf ); \section{\{My subreport\}} \emph{This report is missing: \{No good reason\}} EOF } sub set_up_chart_configs { my $self = $_[0]; $self->{'cfg'}{'_lr_config_spec'} = new Lire::Config::ConfigSpec(); $self->set_up_plugin_mgr(); my $type = new_proxy Lire::Test::Mock( 'Lire::ChartType' ); $type->set_result( 'name' => 'mock_chart', 'write_chart' => sub { return '/tmp/chart.eps' } ); Lire::PluginManager->register_plugin( $type ); $self->{'mock_chart'} = $type; $self->{'cfg'}{'lr_chart_font'} = ''; $self->{'chart1'} = new Lire::Report::ChartConfig(); $self->{'chart1'}->type( $type ); $self->{'chart2'} = new Lire::Report::ChartConfig(); $self->{'chart2'}->type( $type ); return; } sub test_write_subreport { my $self = $_[0]; $self->set_up_chart_configs(); my $subreport = new Lire::Report::Subreport( 'test', 'test1' ); $subreport->title( "{Subreport's Title}" ); $subreport->description( "Subreport's description" ); $subreport->add_chart_config( $self->{'chart1'} ); $subreport->add_chart_config( $self->{'chart2'} ); $self->{'writer'}->set_result( 'write_chart', '' ); $self->{'writer'}->set_result( 'write_table_header', '' ); $self->{'writer'}->set_result( 'write_table_entries', '' ); $self->{'writer'}->set_result( 'write_table_footer', '' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_subreport( $subreport ); $self->assert_str_equals( <<'EOF', $$buf ); \section{\{Subreport's Title\}} Subreport's description EOF $self->assert_num_equals( 2, $self->{'writer'}->invocation_count( 'write_chart' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_table_header' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_table_entries' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_table_footer' ) ); } sub test_write_chart { my $self = $_[0]; $self->set_up_chart_configs(); my $subreport = new Lire::Report::Subreport( 'test', 'test1' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}{'_outputdir'} = $self->{'tmpdir'}; $self->{'writer'}->write_chart( $subreport, $self->{'chart1'} ); $self->assert_str_equals( <<'EOF', $$buf ); \begin{center} \includegraphics{chart.eps} \end{center} EOF $self->assert_deep_equals( [ $self->{'mock_chart'}, $self->{'chart1'}, $subreport, 'outputdir', $self->{'tmpdir'}, 'format', 'eps', 'font', '/Helvetica', ], $self->{'mock_chart'}->get_invocation( 'write_chart' ) ); $self->assert_deep_equals( [ '/tmp/chart.eps' ], $self->{'writer'}{'_chart_files'} ); $self->{'cfg'}{'lr_chart_font'} = '/Times-New-Roman'; $self->{'writer'}->write_chart( $subreport, $self->{'chart1'} ); $self->assert_deep_equals( [ $self->{'mock_chart'}, $self->{'chart1'}, $subreport, 'outputdir', $self->{'tmpdir'}, 'format', 'eps', 'font', '/Times-New-Roman', ], $self->{'mock_chart'}->get_invocation( 'write_chart', 1 ) ); $self->{'mock_chart'}->set_result( 'write_chart', sub { die "An error occured\n" } ); $$buf = ''; $self->{'writer'}->write_chart( $subreport, $self->{'chart1'} ); $self->assert_str_equals( <<'EOF', $$buf ); \emph{An error occured while generating the chart: An error occured } EOF $self->{'mock_chart'}->set_result( 'write_chart', sub { return undef } ); $$buf = ''; $self->{'writer'}->write_chart( $subreport, $self->{'chart1'} ); $self->assert_str_equals( '', $$buf ); return; } sub set_up_subreport { my $self = $_[0]; my $subreport = new Lire::Report::Subreport( 'test', 'test1' ); my $table_info = new Lire::Report::TableInfo(); $table_info->create_column_info( 'user', 'categorical', 'string', '{User}' ); my $group = $table_info->create_group_info( 'group1' ); $group->create_column_info( 'file', 'categorical', 'string', '{File}' ); $group->create_column_info( 'count', 'numerical', 'int', 'Downloads' ); $group->create_column_info( 'size', 'numerical', 'bytes', 'Size' ); $table_info->compute_group_layout(); $subreport->table_info( $table_info ); $subreport->schemas( 'test' ); $self->{'subreport'} = $subreport; return; } sub test_write_table_header { my $self = $_[0]; $self->init(); $self->set_up_test_schema(); $self->set_up_subreport(); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_table_header( $self->{'subreport'} ); $self->assert_str_equals( <<'EOF', $$buf ); \begin{longtable}{|llrr|} \hline \multicolumn{2}{|l}{\bfseries \hyperlink{test:user}{\{User\}}} & \bfseries Downloads & \bfseries Size\\ & \bfseries \hyperlink{test:file}{\{File\}} & & \\ \hline \endhead EOF return; } sub test_write_table_footer { my $self = $_[0]; $self->set_up_subreport(); $self->{'subreport'}->nrecords( 100 ); $self->{'subreport'}->set_summary_value( 'count', 'content' => '356' ); $self->{'subreport'}->set_summary_value( 'size', 'value' => 1024 * 1024, 'content' => '1$' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_table_footer( $self->{'subreport'} ); $self->assert_str_equals( <<'EOF', $$buf ); \hline \multicolumn{4}{r}{\emph{continued on next page}} \endfoot \hline \multicolumn{2}{|l}{\emph{Total for 100 records}} & 356 & 1\$\\ \hline \endlastfoot EOF } sub set_up_subreport_data { my $self = $_[0]; my $data = [ [ 'flacoste', undef, 9, 53 ], [ undef, 'page1.html', 5, 50 ], [ undef, 'page2.html', 4, 3 ], [ '{wsourdeau}', undef, 5, 10 ], [ undef, 'page3.html$', 3, 6 ], [ undef, 'page2.html', 1, 2 ], [ undef, 'page4.html', 1, 2 ] ]; my $group; foreach my $r ( @$data ) { my ( $user, $page, $count, $size ) = @$r; if ( $user ) { my $entry = $self->{'subreport'}->create_entry(); $entry->add_name( $user ); $group = $entry->create_group(); $group->set_summary_value( 'count', 'content' => $count ); $group->set_summary_value( 'size', 'content' => $size ); } else { my $entry = $group->create_entry(); $entry->add_name( $page ); $entry->add_value( 'content' => $count ); $entry->add_value( 'content' => $size ); } } $self->{'subreport'}->finalize(); } sub test_write_table_entries { my $self = $_[0]; $self->set_up_subreport(); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_table_entries( $self->{'subreport'} ); $self->assert_str_equals( <<'EOF', $$buf ); \multicolumn{4}{|l|}{\emph{There is no entries in this table.}}\\ \end{longtable} EOF $self->set_up_subreport_data(); $$buf = ''; $self->{'writer'}->write_table_entries( $self->{'subreport'} ); $self->assert_str_equals( <<'EOF', $$buf ); \multicolumn{2}{|l}{flacoste} & 9 & 53\\ & page1.html & 5 & 50\\ & page2.html & 4 & 3\\ \multicolumn{2}{|l}{\{wsourdeau\}} & 5 & 10\\ & page3.html\$ & 3 & 6\\ & page2.html & 1 & 2\\ & page4.html & 1 & 2\\ \end{longtable} EOF } sub test_write_appendix { my $self = $_[0]; my $report = new Lire::Report(); my $sect = new Lire::Report::Section( 'Title' ); $report->add_section( $sect ); my $sub = new Lire::Report::Subreport( 'test', 'top-dirs' ); $sub->id( 'top-dirs.0' ); $sub->schemas( 'test', 'test-extended' ); $sect->add_subreport( $sub ); $self->{'writer'}->set_result( 'write_schema', '' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_appendix( $report ); $self->assert_str_equals( "\\appendix\n", $$buf ); $self->assert_num_equals( 2, $self->{'writer'}->invocation_count( 'write_schema' ) ); } sub test_write_schema { my $self = $_[0]; my $test_schema = new Lire::DlfSchema( 'superservice' => 'test', 'timestamp' => 'time' ); $test_schema->title( '{A title}' ); $test_schema->description( 'A description.' ); $test_schema->add_field( new Lire::Field( 'name' => 'time', 'type' => 'timestamp', 'label' => '{Time}', 'description' => 'The time field.' ) ); $test_schema->add_field( new Lire::Field( 'name' => 'field_1', 'type' => 'string', 'label' => 'Field 1', 'description' => 'The first field.' ) ); local $Lire::DlfSchema::SCHEMA_CACHE{'test'} = $test_schema; my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_schema( 'test' ); $self->assert_str_equals( <<'EOF', $$buf ); \chapter{\{A title\}} A description. \begin{description} \item[\hypertarget{test:time}{\{Time\}}] The time field. \item[\hypertarget{test:field_1}{Field 1}] The first field. \end{description} EOF } sub set_up_write_report { my $self = $_[0]; $self->init(); $self->set_up_test_schema(); $self->set_up_chart_types(); $self->{'keep_tmpdir'} = $ENV{'KEEP_LATEX'}; my $spec = $self->{'cfg'}{'_lr_config_spec'}; $self->{'cfg'}{'unicode.tex'} = "$self->{'testdir'}/../../../extras/unicode.tex"; $self->{'cfg'}{'lambda_path'} = $spec->get( 'lambda_path' )->default()->as_value(); $self->{'cfg'}{'odvips_path'} = $spec->get( 'odvips_path' )->default()->as_value(); $self->{'cfg'}{'ps2pdf_path'} = $spec->get( 'ps2pdf_path' )->default()->as_value(); my $parser = new Lire::ReportParser::ReportBuilder(); $self->{'report'} = $parser->parsefile( "$self->{'testdir'}/data/TestReport_daily_jan25_2003.xml" ); $self->{'writer'} = new Lire::ReportParser::LaTeXWriter(); } sub test_write_report_latex { my $self = $_[0]; $self->set_up_write_report(); $self->{'writer'}->write_report( $self->{'report'}, "$self->{'tmpdir'}/report.tex", 'latex' ); $self->assert( -s "$self->{'tmpdir'}/report.tex", "missing '$self->{'tmpdir'}/report.tex'" ); print "\nLaTeX report generated in $self->{'tmpdir'}/report.tex\n" if $self->{'keep_tmpdir'}; } sub test_write_report_dvi { my $self = $_[0]; $self->set_up_write_report(); $self->assert( $self->{'cfg'}{'lambda_path'}, "Can't test without lambda" ); $self->{'writer'}->write_report( $self->{'report'}, "$self->{'tmpdir'}/report.dvi", 'dvi' ); $self->assert( -s "$self->{'tmpdir'}/report.dvi", "missing '$self->{'tmpdir'}/report.dvi'" ); $self->assert( ! -f "$self->{'tmpdir'}/report.tex", "file $self->{'tmpdir'}/report.tex wasn't removed" ); $self->assert( ! -f "$self->{'tmpdir'}/report.log", "temporary $self->{'tmpdir'}/report.log wasn't removed" ); $self->assert( ! -f "$self->{'tmpdir'}/report.aux", "temporary $self->{'tmpdir'}/report.aux wasn't removed" ); print "\nDVI report generated in $self->{'tmpdir'}/report.dvi\n" if $self->{'keep_tmpdir'}; } sub test_write_report_ps { my $self = $_[0]; $self->set_up_write_report(); $self->assert( $self->{'cfg'}{'lambda_path'}, "Can't test without lambda" ); $self->assert( $self->{'cfg'}{'odvips_path'}, "Can't test without odvips" ); $self->{'writer'}->write_report( $self->{'report'}, "$self->{'tmpdir'}/report.ps", 'ps' ); $self->assert( -s "$self->{'tmpdir'}/report.ps", "missing '$self->{'tmpdir'}/report.ps'" ); $self->assert( ! -f "$self->{'tmpdir'}/report.dvi", "temporary $self->{'tmpdir'}/report.dvi wasn't removed" ); print "\nPS report generated in $self->{'tmpdir'}/report.ps\n" if $self->{'keep_tmpdir'}; } sub test_write_report_pdf { my $self = $_[0]; $self->set_up_write_report(); $self->assert( $self->{'cfg'}{'lambda_path'}, "Can't test without lambda" ); $self->assert( $self->{'cfg'}{'odvips_path'}, "Can't test without odvips" ); $self->assert( $self->{'cfg'}{'ps2pdf_path'}, "Can't test without ps2pdf" ); $self->{'writer'}->write_report( $self->{'report'}, "$self->{'tmpdir'}/report.pdf", 'pdf' ); $self->assert( -s "$self->{'tmpdir'}/report.pdf", "missing '$self->{'tmpdir'}/report.pdf'" ); $self->assert( ! -f "$self->{'tmpdir'}/report.ps", "temporary $self->{'tmpdir'}/report.ps wasn't removed" ); print "\nPDF report generated in $self->{'tmpdir'}/report.pdf\n" if $self->{'keep_tmpdir'}; } 1; lire-2.1.1/all/lib/tests/DlfResultTest.pm0000644000175000017500000001435310460672600015160 00000000000000package tests::DlfResultTest; use strict; use base qw/ tests::TestStoreFixture Lire::Test::TestCase /; use Lire::DlfQuery; use Lire::DlfResult; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); return $self; } sub set_up { my $self = shift->SUPER::set_up(); $self->set_up_test_store(); $self->set_up_simple_query(); } sub set_up_simple_query { my $self = $_[0]; my $query = new Lire::DlfQuery( 'test' ); foreach my $f ( qw/time_start user file/ ) { $query->add_field( $f ); } $query->set_filter_clause( 'user = ?', 'flacoste' ); $query->set_order_by_clause( 'time_start' ); $self->{'simple_query'} = $query; } sub set_up_utf8_query { my $self = $_[0]; $self->{'uni_string'} = "ISO eacute: \xe9"; my $utf8_string = "ISO eacute: \x{c3}\x{a9}"; $self->{'store'}{'_dbh'}->do( 'INSERT INTO dlf_test ( user, file ) VALUES( ?, ? )', {}, 'utf8_test', $utf8_string ); my $query = new Lire::DlfQuery( 'test' ); $query->add_field( 'file' ); $query->set_filter_clause( 'user = ?', 'utf8_test' ); $self->{'utf8_query'} = $query; return; } sub tear_down { my $self = shift->SUPER::tear_down(); $self->tear_down_test_store(); $self->{'simple_query'}->release(); } sub test_new { my $self = $_[0]; $self->assert_died( sub { new Lire::DlfResult() }, qr/missing 'query' parameter/ ); $self->assert_died( sub { new Lire::DlfResult( $self->{'simple_query'} ) }, qr/missing 'sql' parameter/ ); $self->assert_died( sub { new Lire::DlfResult( $self->{'simple_query'}, $self->{'simple_query'}->_as_sql() ) }, qr/missing 'store' parameter/ ); my $result = new Lire::DlfResult( $self->{'simple_query'}, $self->{'simple_query'}->_as_sql(), $self->{'store'} ); $self->assert_not_null( $result, "new() returned undef" ); $self->assert( UNIVERSAL::isa( $result, 'Lire::DlfResult' ), "new() didn't return a Lire::DlfResult instance: $result" ); $self->assert_deep_equals( $self->{'simple_query'}, $result->{'_query'} ); $self->assert_not_null( $result->{'_sth'}, "'_sth' attribute wasn't initialized" ); $self->assert( defined UNIVERSAL::can( $result->{'_sth'}, 'fetchrow_arrayref' ), "'_sth' attribute doesn't seem to be a DBI statement handle: $result->{'_sth'}" ); } sub test_next_row { my $self = $_[0]; my $result = $self->{'simple_query'}->execute( $self->{'store'} ); my @rows = ( { 'time_start' => 1043514300, 'user' => 'flacoste', 'file' => '/movies/000002.mpg', }, { 'time_start' => 1043515075, 'user' => 'flacoste', 'file' => '/movies/000003.mpg', }, ); my $row1 = $result->next_row(); $self->assert_deep_equals( $rows[0], $row1 ); my $row2 = $result->next_row(); $self->assert_deep_equals( $rows[1], $row2 ); $self->assert_not_equals( $row1, $row2 ); $self->assert_null( $result->next_row(), "next_row() should return undef when there is no more data" ); $self->assert_died( sub { $result->next_row() }, qr/next_row\(\) called after undef was returned by previous call/ ); } sub test_next_row_quoting { my $self = $_[0]; my $query = new Lire::DlfQuery( 'test', $self->{'store'} ); foreach my $f ( qw/time_start transfer-complete/ ) { $query->add_field( $f ); } $query->set_order_by_clause( 'time_start' ); my $result = $query->execute( $self->{'store'} ); $self->assert_deep_equals( { 'time_start' => 1043514000, 'transfer-complete' => 1 }, $result->next_row() ); } sub test_next_row_utf8 { my $self = $_[0]; # Under 5.6, DlfStore should only contain ASCII return unless $Lire::I18N::USE_ENCODING; $self->set_up_utf8_query(); my $result = $self->{'utf8_query'}->execute( $self->{'store'} ); my $row = $result->next_row(); $self->assert_str_equals( $self->{'uni_string'}, $row->{'file'} ); } sub test_next_row_aref { my $self = $_[0]; my $result = $self->{'simple_query'}->execute( $self->{'store'} ); my @rows = ( [ 1043514300, 'flacoste', '/movies/000002.mpg', ], [ 1043515075, 'flacoste', '/movies/000003.mpg' ], ); my $row1 = $result->next_row_aref(); $self->assert_deep_equals( $rows[0], $row1 ); my $row2 = $result->next_row_aref(); $self->assert_deep_equals( $rows[1], $row2 ); $self->assert_not_equals( $row1, $row2 ); $self->assert_null( $result->next_row_aref(), "next_row_aref() should return undef when there is no more data" ); $self->assert_died( sub { $result->next_row_aref() }, qr/next_row_aref\(\) called after undef was returned by previous call/ ); } sub test_next_row_and_next_row_aref_mix { my $self = $_[0]; my $result = $self->{'simple_query'}->execute( $self->{'store'} ); $result->next_row(); $result->next_row_aref(); $self->assert_null( $result->next_row(), "next_row() should return undef when there is no more data" ); $self->assert_died( sub { $result->next_row_aref() }, qr/next_row_aref\(\) called after undef was returned by previous call/ ); $self->assert_died( sub { $result->next_row() }, qr/next_row\(\) called after undef was returned by previous call/ ); } sub test_next_row_aref_utf8 { my $self = $_[0]; # Under 5.6, DlfStore should only contain ASCII return unless $Lire::I18N::USE_ENCODING; $self->set_up_utf8_query(); my $result = $self->{'utf8_query'}->execute( $self->{'store'} ); my $row = $result->next_row_aref(); $self->assert_str_equals( $self->{'uni_string'}, $row->[0] ); } 1; lire-2.1.1/all/lib/tests/schemas/0000755000175000017500000000000011677607770013574 500000000000000lire-2.1.1/all/lib/tests/schemas/test.xml0000644000175000017500000000405610460672602015203 00000000000000 Simple Schema Definition for Test Simple schema definition for testing purpose Start time of the file transfer. The time at which the transfer ended. Time taken by the transfer. Connection identifier. The host to which the file was transferred. Name of the authenticated user that did the file transfer. The file that was transferred. The number of bytes transferred. Was the file transferred completely? lire-2.1.1/all/lib/tests/schemas/test-extended.xml0000644000175000017500000000133410460672602016775 00000000000000 Simple Extended Schema for Tests Simple extended schema for testing purpose. Contains the file's directory. lire-2.1.1/all/lib/tests/schemas/test-derived.xml0000644000175000017500000000223510460672602016620 00000000000000 Simple Derived Schema for Tests Simple derived schema for testing purpose. This schema is redundant with the base schema, but it is only for testing purpose. This field isn't supported by the analyzer. lire-2.1.1/all/lib/tests/UIReportConfigListWidgetTest.pm0000644000175000017500000000575610460672601020123 00000000000000package tests::UIReportConfigListWidgetTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::Config::TypeSpec; use Lire::Test::CursesUIDriver; use Lire::UI::ReportConfigListWidget; use Lire::ReportConfig; use Curses::UI; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'driver'} = new Lire::Test::CursesUIDriver(); $self->{'driver'}->setup_curses_ui(); $self->{'ui'} = new Curses::UI(); $self->{'driver'}->set_curses_ui( $self->{'ui'} ); $self->{'window'} = $self->{'ui'}->add( 'window', 'Window' ); $self->{'_old_templates'} = \%Lire::ReportConfig::TEMPLATES; my $spec = new Lire::Config::ListSpec( 'name' => 'reports' ); $spec->add( new Lire::Config::ReportSpec( 'name' => 'report' ) ); $self->{'ftp_default'} = new Lire::Config::ReportSpec( 'name' => 'ftp_default' )->instance(); $self->{'www_default'} = new Lire::Config::ReportSpec( 'name' => 'www_default' )->instance(); *Lire::ReportConfig::TEMPLATES = { 'ftp_default' => $self->{'ftp_default'}, 'www_default' => $self->{'www_default'}, }; $self->{'ftp_default'}->get( 'id' )->set( 'ftp_default' ); $self->{'www_default'}->get( 'id' )->set( 'www_default' ); $self->{'cfg'}{'lr_templates_path'} = []; $self->{'reports'} = $spec->instance(); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); *Lire::ReportConfig::TEMPLATES = $self->{'_old_templates'}; $self->{'driver'}->teardown_curses_ui(); return; } sub test_update_type_popupmenu { my $self = $_[0]; my $widget = $self->{'window'}->add( 'list_widget', 'Lire::UI::ReportConfigListWidget', 'value' => $self->{'reports'} ); $self->assert_isa( 'Lire::UI::ReportConfigListWidget', $widget ); $self->assert_deep_equals( [ 'ftp_default', 'www_default' ], $widget->getobj( 'type_widget' )->{'-values'} ); $self->assert_deep_equals( {}, $widget->getobj( 'type_widget' )->{'-labels'} ); } sub test_new_value { my $self = $_[0]; my $widget = $self->{'window'}->add( 'list_widget', 'Lire::UI::ReportConfigListWidget', 'value' => $self->{'reports'} ); my $popup = $widget->getobj( 'type_widget' ); $self->assert_null( $widget->new_value(), 'new_value() != undef' ); $popup->{'-selected'} = 0; my $value = $widget->new_value(); $self->assert_isa( 'Lire::Config::Object', $value ); $self->assert_str_not_equals( $self->{'ftp_default'}, $value ); $self->assert_str_equals( 'ftp_default', $value->get( 'id' )->get() ); $self->assert_str_equals( $self->{'reports'}->spec()->get( 'report' ), $value->spec() ); $popup->{'-selected'} = 1; $value = $widget->new_value(); $self->assert_str_equals( 'www_default', $value->get( 'id' )->get() ); } 1; lire-2.1.1/all/lib/tests/ReportSpecTest.pm0000644000175000017500000003035610460672577015360 00000000000000package tests::ReportSpecTest; use strict; use base qw/ Lire::Test::TestCase tests::TestStoreFixture tests::ChartTypesFixture /; use Lire::ReportSpec; use Lire::DlfSchema; use Lire::FilterExpr; use Lire::Param; use Lire::Group; use Lire::GroupField; use Lire::Aggregate; use Lire::Report; use Lire::Utils qw/tempdir create_file/; use Lire::Config::XMLSpecListSpec; use tests::MockAggregator; use tests::MockAggregate; use Lire::Report::ChartConfig; use Lire::Test::Mock; sub new { my $self = shift->SUPER::new( @_ ); $self->init(); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->set_up_test_store(); $self->{'tmp_test_spec_dir'} = $self->{'tmpdir'} . "/test"; mkdir $self->{'tmp_test_spec_dir'} or $self->error( "failed to make $self->{'tmp_test_spec_dir'}: $!\n" ); $self->{'cfg'}{'lr_reports_path'} = [ $self->{'testdir'} . "/reports", $self->{'tmpdir'} ]; $self->set_up_simple_report_spec(); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down( @_ ); return; } sub test_load_report { my $self = $_[0]; my $spec = Lire::ReportSpec->load( "test", "top-files" ); $self->assert_str_equals( "top-files", $spec->id() ); } sub create_test_report_spec { my $self = $_[0]; my $spec = new Lire::ReportSpec(); $spec->id( "test-report" ); $spec->superservice( "test" ); $spec->title( "Test Report Specification" ); $spec->description( "Test Report Specification" ); $spec->display_title( "Test Report" ); $spec->param( "param_int", new Lire::Param( 'name' => "param_int", 'type' => "int", 'i18n_domain' => 'lire-test', ) ); $spec->param( "param_int" )->default( 10 ); $spec->param( "param_match", new Lire::Param( 'name' => "param_match", 'type' => "string", 'i18n_domain' => 'lire-test', ) ); $spec->param( "param_match" )->default( ".*" ); my $cfg = new Lire::Report::ChartConfig(); $cfg->name( 'test-chart' ); $cfg->title( 'Downloads Pie' ); $cfg->get( 'case_var' )->set( 'file' ); $cfg->type( Lire::PluginManager->get_plugin( 'chart_type', 'pie' ) ); $cfg->type_properties()->get( 'values' )->set( 'downloads' ); $spec->add_chart_config( $cfg ); $spec->filter_spec( new Lire::FilterExpr::Match( 'container' => $spec, 'value' => '$file', 're' => '$param_match', ) ); my $group = new Lire::Group( 'report_spec' => $spec, 'limit' => '$param_int', ); $group->group_fields( [ new Lire::GroupField( 'report_spec' => $spec, 'name' => "file", 'i18n_domain' => 'lire-test', ) ] ); $group->ops( [ new Lire::Count( 'report_spec' => $spec, 'parent' => $group, 'name' => "downloads", 'label' => "Downloads", ) ] ); $group->sort_fields( [ "-downloads" ] ); $spec->calc_spec( $group ); return $spec; } sub set_up_simple_report_spec { my $self = $_[0]; $self->{'simple_spec'} = new Lire::ReportSpec(); $self->{'simple_spec'}->superservice( 'test' ); $self->{'simple_spec'}->id( 'test-spec' ); $self->{'simple_spec'}->subreport_id( "test-spec.i" ); $self->{'simple_spec'}->param( 'param1', new Lire::Param( 'name' => 'param1', 'type' => 'int', 'i18n_domain' => 'lire-test', 'default' => 5 ) ); $self->{'simple_spec'}->charttype( 'bars' ); $self->{'simple_spec'}->display_title( 'Top $param1 report' ); $self->{'simple_spec'}->display_description( '$param1' ); my $aggr = new_proxy Lire::Test::Mock( 'tests::MockAggregator', 'report_spec' => $self->{'simple_spec'} ); $aggr->set_result( 'create_entries' => sub { # Create two empty entries $_[1]->create_entry(); $_[1]->create_entry(); } ); $aggr->ops( [ new tests::MockAggregate( 'report_spec' => $self->{'simple_spec'}, 'parent' => $aggr, 'name' => 'aggr' ) ] ); $self->{'simple_spec'}->calc_spec( $aggr ); return; } sub test_print { my $self = $_[0]; $self->set_up_chart_types(); my $spec = $self->create_test_report_spec(); my $specfile = "$self->{'tmp_test_spec_dir'}/test-report.xml"; open my $fh, "> $specfile" or $self->error( "failed to open $specfile for writing: $!\n" ); $spec->print( $fh ); close $fh or $self->error( "close failed: $!\n" ); my $spec2 = Lire::ReportSpec->load( $spec->superservice(), $spec->id() ); $self->assert_deep_equals( $spec, $spec2 ); } sub test_create_subreport { my $self = $_[0]; $self->set_up_chart_types(); my $subreport = $self->{'simple_spec'}->create_subreport(); $self->assert_isa( 'Lire::Report::Subreport', $subreport ); $self->assert_str_equals( 'test-spec', $subreport->type() ); $self->assert_str_equals( 'test-spec.i', $subreport->id() ); $self->assert_num_equals( 1, scalar @{$subreport->chart_configs()} ); $self->assert_str_equals( 'Top 5 report', $subreport->title() ); $self->assert_str_equals( '5', $subreport->description() ); $self->assert_str_equals( 2, scalar $subreport->entries() ); $self->assert_str_equals( 1, ($subreport->entries())[1]->row_idx() ); $self->assert_isa( 'Lire::Report::TableInfo', $subreport->table_info() ); $self->assert_num_equals( 1, $subreport->table_info()->column_info_by_name( 'aggr' )->col_start() ); } sub test_create_subreport_missing { my $self = $_[0]; my $spec = $self->{'simple_spec'}; $spec->mark_missing( 'Bogus reason' ); my $report = new Lire::Report(); my $subreport = $spec->create_subreport( $report ); $self->assert_isa( 'Lire::Report::Subreport', $subreport ); $self->assert_str_equals( 'test-spec', $subreport->type() ); $self->assert_str_equals( 'test-spec.i', $subreport->id() ); $self->assert( $subreport->is_missing(), 'is_missing() should return true' ); $self->assert_str_equals( 'Bogus reason', $subreport->missing_reason() ); } sub test_set_store { my $self = $_[0]; my $spec = new Lire::ReportSpec(); $spec->id( 'test-spec' ); $spec->{'superservice'} = 'test-extended'; my $aggr = new tests::MockAggregator( 'report_spec' => $spec ); $spec->calc_spec( $aggr ); $self->assert_dies( qr/missing 'store' parameter/, sub { $spec->set_store() } ); $self->assert_dies( qr/'store' parameter should be a 'Lire::DlfStore' instance, not 'HASH/, sub { $spec->set_store( {} ) } ); $self->assert_dies( qr/store doesn't contain a 'test-extended' DLF stream/, sub { $spec->set_store( $self->{'store'} ) } ); $spec->{'superservice'} = 'test'; $spec->set_store( $self->{'store'} ); $self->assert_equals( $self->{'store'}, $aggr->{'store'} ); } sub test_new_from_config { my $self = $_[0]; $self->{'cfg'}{'lr_reports_path'} = [ "$self->{'testdir'}/reports" ]; $self->set_up_chart_types(); my $e_spec = Lire::ReportSpec->load( 'test', 'top-dirs2' ); $e_spec->subreport_id( 'my-top-dirs' ); $e_spec->param( 'dirs_to_show' )->value( 10 ); my $list_spec = new Lire::Config::XMLSpecListSpec( 'name' => 'test', 'type' => 'reports' ); my $list = $list_spec->instance(); my $spec = $list_spec->get( 'test:top-dirs2' )->instance(); $spec->get( 'id' )->set( 'my-top-dirs' ); $list->append( $spec ); $e_spec->chart_configs()->[0]->spec()->summary( $spec->spec()->get( 'charts' )->get( 'chart' )->summary() ); $e_spec->chart_configs()->[0]->spec()->description( $spec->spec()->get( 'charts' )->get( 'chart' )->description() ); $self->assert_deep_equals( [ $e_spec ], $list->as_value() ); $spec->get( 'title' )->set( 'My custom title' ); $spec->get( 'dirs_to_show' )->set( 5 ); $spec->get( 'charts' )->get( 0 )->get( 'title' )->set( 'My test chart' ); $e_spec->display_title( 'My custom title' ); $e_spec->param( 'dirs_to_show' )->value( 5 ); $e_spec->chart_configs()->[0]->title( 'My test chart' ); $self->assert_deep_equals( [ $e_spec ], $list->as_value() ); } sub set_up_chart_report_spec { my $self = $_[0]; my $spec = new Lire::ReportSpec(); $self->assert_null( $spec->{'_chart_configs'}, '_chart_configs != undef' ); $spec->superservice( 'test' ); $spec->id( 'test-chart' ); $spec->subreport_id( 'test-chart.0' ); my $outer = new tests::MockAggregator( 'name' => 'outer', 'report_spec' => $spec ); my $inner = new tests::MockAggregator( 'name' => 'inner', 'parent' => $outer, 'report_spec' => $spec ); $inner->ops( [ new tests::MockAggregate( 'name' => 'value1', 'parent' => $inner, 'report_spec' => $spec ), new tests::MockAggregate( 'name' => 'value2', 'parent' => $inner, 'report_spec' => $spec ) ] ); $outer->ops( [ $inner ] ); $spec->calc_spec( $outer ); $self->{'spec'} = $spec; return; } sub test_default_chart_config { my $self = $_[0]; $self->set_up_chart_types(); $self->set_up_chart_report_spec(); my $cfg = new Lire::Report::ChartConfig(); $cfg->basename( 'test-chart.0' ); $cfg->get( 'case_var' )->set( 'outer' ); $self->{'spec'}->charttype( undef ); $self->assert_null( $self->{'spec'}->default_chart_config(), 'default_chart_config != undef' ); $self->{'spec'}->charttype( 'bars' ); $cfg->type( Lire::PluginManager->get_plugin( 'chart_type', 'vbars' ) ); $cfg->type_properties()->get( 'y' )->set( 'value1' ); $self->assert_deep_equals( $cfg, $self->{'spec'}->default_chart_config() ); $self->{'spec'}->charttype( 'histogram' ); $self->assert_deep_equals( $cfg, $self->{'spec'}->default_chart_config() ); $self->{'spec'}->charttype( 'lines' ); $cfg->type( Lire::PluginManager->get_plugin( 'chart_type', 'lines' ) ); $cfg->type_properties()->get( 'y' )->set( 'value1' ); $self->assert_deep_equals( $cfg, $self->{'spec'}->default_chart_config() ); $self->{'spec'}->charttype( 'pie' ); $cfg->type( Lire::PluginManager->get_plugin( 'chart_type', 'pie' ) ); $cfg->type_properties()->get( 'values' )->set( 'value1' ); $self->assert_deep_equals( $cfg, $self->{'spec'}->default_chart_config() ); } sub test_chart_configs { my $self = $_[0]; $self->set_up_chart_types(); $self->set_up_chart_report_spec(); $self->{'spec'}->charttype( undef ); $self->assert_deep_equals( [], $self->{'spec'}->chart_configs() ); $self->{'spec'}->charttype( 'bars' ); $self->assert_deep_equals( [ $self->{'spec'}->default_chart_config() ], $self->{'spec'}->chart_configs() ); $self->assert_null( $self->{'spec'}{'_chart_configs'} ); my $cfg = new Lire::Report::ChartConfig(); $self->{'spec'}->add_chart_config( $cfg ); $self->assert_deep_equals( [ $cfg ], $self->{'spec'}{'_chart_configs'} ); $self->assert_deep_equals( [ $cfg ], $self->{'spec'}->chart_configs() ); } 1; lire-2.1.1/all/lib/tests/config.pm0000644000175000017500000000102110460672600013645 00000000000000package tests::config; use File::Basename qw/dirname/; use Cwd qw/realpath/; use base 'Test::Unit::TestSuite'; sub name { 'All Lire Config Unit Tests' } sub include_tests { # Files containing test cases all ends in Test.pm my $dir = realpath( dirname(__FILE__) ); opendir DIR, $dir or die "can't opendir $dir: $!"; my @tests = (); foreach my $e ( readdir DIR ) { next unless $e =~ /^(Config.*Test)\.pm$/; push @tests, "tests::$1"; } closedir DIR; return @tests; } 1; lire-2.1.1/all/lib/tests/UIStoreWindowTest.pm0000644000175000017500000003242710460672600016000 00000000000000package tests::UIStoreWindowTest; use strict; use base qw/ Lire::Test::TestCase /; use Curses::UI; use Lire::DlfStore; use Lire::UI::StoreWindow; use Lire::Test::Mock; use Lire::Test::CursesUIDriver; use Lire::Config::Dictionary; use Lire::Config::DlfStreamSpec; use Time::Local; sub new { my $self = shift->SUPER::new( @_ ); $self->{'driver'} = new Lire::Test::CursesUIDriver(); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->set_up_tz( 'EST' ); my $spec = $self->lire_default_config_spec(); $self->{'cfg'}{'_lr_config_spec'} = $spec; $self->{'cfg'}{'lr_templates_path'} = []; $self->{'mock_stream'} = new Lire::Test::Mock( 'Lire::DlfStream', 'start_time' => '1072933200', 'end_time' => '1104555600', 'nrecords' => 1 ); $self->{'store'} = new Lire::Test::Mock( 'Lire::DlfStore', 'path' => 'mystore', 'config' => $spec->instance() ); $self->{'driver'}->setup_curses_ui(); $self->{'ui'} = new Curses::UI(); $self->{'driver'}->set_curses_ui( $self->{'ui'} ); return; } sub tear_down { my $self = $_[0]; $self->{'driver'}->teardown_curses_ui(); $self->SUPER::tear_down(); return; } sub test_new { my $self = $_[0]; my $ui = $self->{'ui'}; $self->assert_dies( qr/missing 'store' parameter/, sub { $ui->add( 'store_win', 'Lire::UI::StoreWindow') } ); $self->assert_dies( qr/'store' parameter should be a 'Lire::DlfStore' instance, not 'HASH/, sub { $ui->add( 'store_win', 'Lire::UI::StoreWindow', 'store' => {} ) } ); my $win = $ui->add( 'store_win', 'Lire::UI::StoreWindow', 'store' => $self->{'store'} ); my $e_object_names = [ 'import_jobs', 'nrecords_label', 'nrecords_value', 'report_jobs', 'reports', 'stream_end_label', 'stream_end_value', 'stream_start_label', 'stream_start_value', 'streams', 'streams_buttons' ]; my @object_names = sort keys %{$win->{'-id2object'}}; $self->assert_deep_equals( $e_object_names, \@object_names ); $self->assert_str_equals( "Store: mystore", $win->title() ); # $self->assert_num_equals( 0, $Curses::UI::screen_too_small ); $self->_test_new_lists( $win ); $self->_test_add_stream_widgets( $win ); $self->assert_isa( 'CODE', $win->getobj( 'import_jobs' )->{'onvaluechanged'} ); return; } sub _test_new_lists { my ( $self, $win ) = @_; my $cfg = $self->{'store'}->config(); my $e_import_jobs_value = $cfg->get( 'import_jobs' ); my $e_report_jobs_value = $cfg->get( 'report_jobs' ); my $e_reports_value = $cfg->get( 'reports' ); my $import_jobs = $win->getobj( 'import_jobs' ); $self->assert_isa( 'Lire::UI::ListWidget', $import_jobs ); $self->assert_str_equals( 'Import Jobs', $import_jobs->title() ); $self->assert_str_equals( $e_import_jobs_value, $import_jobs->{'value'} ); my $report_jobs = $win->getobj( 'report_jobs' ); $self->assert_isa( 'Lire::UI::ListWidget', $report_jobs ); $self->assert_str_equals( $e_report_jobs_value, $report_jobs->{'value'} ); $self->assert_str_equals( 'Report Jobs', $report_jobs->title() ); my $reports = $win->getobj( 'reports' ); $self->assert_isa( 'Lire::UI::ReportConfigListWidget', $reports ); $self->assert_str_equals( $e_reports_value, $reports->{'value'} ); $self->assert_str_equals( 'Report Configurations', $reports->title() ); return; } sub _test_add_stream_widgets { my ( $self, $win ) = @_; my $streams = $win->getobj( 'streams' ); $self->assert_isa( 'Curses::UI::Listbox', $streams ); $self->assert_str_equals( 'DLF Streams', $streams->title() ); my $streams_buttons = $win->getobj( 'streams_buttons' ); $self->assert_isa( 'Curses::UI::Buttonbox', $streams_buttons ); $self->assert_num_equals( 2, scalar @{$streams_buttons->{'-buttons'}} ); $self->assert_str_equals( '[Configure]', $streams_buttons->{'-buttons'}[0]{'-label'} ); $self->assert_str_equals( '[Clean]', $streams_buttons->{'-buttons'}[1]{'-label'} ); my $stream_start_label = $win->getobj( 'stream_start_label' ); $self->assert_isa( 'Curses::UI::Label', $stream_start_label ); $self->assert_str_equals( 'Starts:', $stream_start_label->{'-text'} ); my $stream_end_label = $win->getobj( 'stream_end_label' ); $self->assert_isa( 'Curses::UI::Label', $stream_end_label ); $self->assert_str_equals( 'Ends:', $stream_end_label->{'-text'} ); my $stream_start_value = $win->getobj( 'stream_start_value' ); $self->assert_isa( 'Curses::UI::Label', $stream_start_value ); my $stream_end_value = $win->getobj( 'stream_end_value' ); $self->assert_isa( 'Curses::UI::Label', $stream_end_value ); my $nrecords_label = $win->getobj( 'nrecords_label' ); $self->assert_isa( 'Curses::UI::Label', $nrecords_label ); my $nrecords_value = $win->getobj( 'nrecords_value' ); $self->assert_isa( 'Curses::UI::Label', $nrecords_value ); return; } sub test_update_labels { my $self = $_[0]; my $win = $self->{'ui'}->add( 'store_win', 'Lire::UI::StoreWindow', 'store' => $self->{'store'} ); my $streams = $win->getobj( 'streams' ); my $stream_start_value = $win->getobj( 'stream_start_value' ); my $stream_end_value = $win->getobj( 'stream_end_value' ); my $nrecords_value = $win->getobj( 'nrecords_value' ); $self->assert_null( $streams->{'-selected'} ); $win->_update_labels(); $self->assert_str_equals( '', $stream_start_value->{'-text'} ); $self->assert_str_equals( '', $stream_end_value->{'-text'} ); $self->assert_str_equals( '', $nrecords_value->{'-text'} ); $self->{'store'}->set_result( 'has_dlf_stream' => 1, 'open_dlf_stream' => $self->{'mock_stream'}); $streams->{'-values'} = [ 'mock_stream' ]; $streams->{'-selected'} = $streams->{'-ypos'} = 0; $streams->{'-focusable'} = 1; $win->_update_labels(); $self->assert_str_equals( '2004-01-01 00:00', $stream_start_value->{'-text'} ); $self->assert_str_equals( '2005-01-01 00:00', $stream_end_value->{'-text'} ); $self->assert_str_equals( 1, $nrecords_value->{'-text'} ); $self->{'store'}->set_result( 'has_dlf_stream' => 0 ); $win->_update_labels(); $self->assert_str_equals( '', $stream_start_value->{'-text'} ); $self->assert_str_equals( '', $stream_end_value->{'-text'} ); $self->assert_str_equals( 0, $nrecords_value->{'-text'} ); return; } sub test_update_streams { my $self = $_[0]; my $win = $self->{'ui'}->add( 'store_win', 'Lire::UI::StoreWindow', 'store' => $self->{'store'} ); $win->_update_streams(); my $streams = $win->getobj( 'streams' ); $self->assert_null( $streams->{'-selected'} ); $self->assert_num_equals( 0, $streams->{'-ypos'} ); $self->assert_num_equals( 0, $streams->{'-focusable'} ); $self->assert_deep_equals( [ '-- no stream --' ], $streams->{'-values'} ); $self->{'store'}->set_result( 'configured_dlf_streams' => 'mock_stream' ); $win->_update_streams(); $self->assert_num_equals( 0, $streams->{'-selected'} ); $self->assert_num_equals( 0, $streams->{'-ypos'} ); $self->assert_num_equals( 1, $streams->{'-focusable'} ); $self->assert_deep_equals ( [ 'mock_stream' ], $streams->{'-values'} ); return; } sub test_clean_stream { my $self = $_[0]; $self->{'store'}->set_result( 'configured_dlf_streams' => 'mock_stream', 'open_dlf_stream' => $self->{'mock_stream'}); my $win = $self->{'ui'}->add( 'store_win', 'Lire::UI::StoreWindow', 'store' => $self->{'store'} ); $self->assert_num_equals( 0, $win->getobj( 'streams' )->{'-selected'} ); my $ok_handler = sub { my $dialog = $_[1]; $self->assert_str_equals( $dialog, $win->getobj( 'clean_stream_win' )); $self->assert_isa( 'Curses::UI::Window', $dialog ); $self->assert_str_equals( "Cleaning stream 'mock_stream'", $dialog->{'-title'} ); my $field = $dialog->getobj( 'time_field' ); $field->text( '2004-03-31' ); $dialog->getobj( 'buttons' )->{'-buttons'}[1]{'-onpress'}->(); }; $self->{'driver'}->add_event_loop_handler( $ok_handler ); $win->getobj( 'streams_buttons' )->{'-buttons'}[1]{'-onpress'}->(); $self->assert_num_equals( 1, $self->{'mock_stream'}->invocation_count( 'clean' ) ); $self->assert_deep_equals( [ $self->{'mock_stream'}, timelocal( 0, 0, 0, 31, 2, 2004 ) ], $self->{'mock_stream'}->get_invocation( 'clean' ) ); $self->assert_null( $win->getobj( 'clean_stream_win' ) ); my $cancel_handler = sub { my $dialog = $_[1]; my $field = $dialog->getobj( 'time_field' ); $field->text( '2004-01-01' ); $dialog->getobj( 'buttons' )->{'-buttons'}[0]{'-onpress'}->(); }; $self->{'driver'}->add_event_loop_handler( $cancel_handler ); $win->getobj( 'streams_buttons' )->{'-buttons'}[1]{'-onpress'}->(); $self->assert_num_equals( 1, $self->{'mock_stream'}->invocation_count( 'clean' ) ); return; } sub test_configure_stream { my $self = $_[0]; my $config = Lire::Config::DlfStreamSpec->new( 'name' => 'mock_stream' )->instance(); $self->assert_num_equals( 60, $config->get( 'keep_days' )->as_value() ); $self->{'store'}->set_result( 'configured_dlf_streams' => 'mock_stream', 'get_stream_config' => $config, 'open_dlf_stream' => $self->{'mock_stream'}); my $win = $self->{'ui'}->add( 'store_win', 'Lire::UI::StoreWindow', 'store' => $self->{'store'} ); $self->assert_num_equals( 0, $win->getobj( 'streams' )->{'-selected'} ); my $called = '_update_streams not called'; no warnings 'redefine'; local *Lire::UI::StoreWindow::_update_streams = sub { $called = 'called' }; my $cancel_handler = sub { my $dialog = $_[1]; $self->assert_str_equals( $dialog, $self->{'ui'}->getobj( 'configure_stream_win' ) ); $self->assert_isa( 'Curses::UI::Window', $dialog ); $self->assert_str_equals( "Configuring stream 'mock_stream'", $dialog->{'-title'} ); my $stream_cfg = $dialog->getobj( 'stream_config' ); $self->assert_isa( 'Lire::UI::CompoundWidget', $stream_cfg ); $self->assert_str_not_equals( $config, $stream_cfg->value() ); $self->assert_deep_equals( $config, $stream_cfg->value() ); $stream_cfg->value()->get( 'keep_days' )->set( 10 ); $dialog->getobj( 'buttons' )->{'-buttons'}[0]{'-onpress'}->(); }; $self->{'driver'}->add_event_loop_handler( $cancel_handler ); $win->getobj( 'streams_buttons' )->{'-buttons'}[0]{'-onpress'}->(); $self->assert_null( $self->{'ui'}->getobj( 'configure_stream_win' ) ); $self->assert_num_equals( 60, $config->get( 'keep_days' )->as_value() ); $self->assert_str_equals( '_update_streams not called', $called ); my $ok_handler = sub { $_[1]->getobj( 'stream_config' )->value()->get( 'keep_days' )->set( 10 ); $_[1]->getobj( 'buttons' )->{'-buttons'}[1]{'-onpress'}->(); }; $self->{'driver'}->add_event_loop_handler( $ok_handler ); $win->getobj( 'streams_buttons' )->{'-buttons'}[0]{'-onpress'}->(); $self->assert_str_equals( 'called', $called ); $self->assert_num_equals( 10, $config->get( 'keep_days' )->as_value() ); return; } sub test_test_date { my $self = $_[0]; foreach my $date ( qw/ 2003-10-04 03-10-04 0000-01-13 0000-01-31 / ) { $self->assert( Lire::UI::StoreWindow::_test_date( $date ), $date ); } foreach my $date (qw/1988 aaaaa 3-10-4 0000-00-00 0000-13-13 2004-01-53/) { $self->assert( !Lire::UI::StoreWindow::_test_date( $date ), $date ); } return; } sub test_date_to_epoch { my $self = $_[0]; my %dates = ( '2004-01-01' => 1072933200, '04-01-01' => 1072933200, '70-01-01' => 18000 ); foreach my $date ( keys %dates ) { $self->assert_num_equals( $dates{$date}, Lire::UI::StoreWindow::_date_to_epoch( $date ) ); } } sub test_epoch_to_date { my $self = $_[0]; my %epochs = ( 1072933200 => '2004-01-01', 18000 => '1970-01-01' ); foreach my $epoch ( keys %epochs ) { $self->assert_num_equals( $epochs{$epoch}, Lire::UI::StoreWindow::_epoch_to_date( $epoch ) ); } $self->assert_str_equals( '-- no date --', Lire::UI::StoreWindow::_epoch_to_date() ); $self->assert_str_equals( '-- no date --', Lire::UI::StoreWindow::_epoch_to_date( '' ) ); } 1; lire-2.1.1/all/lib/tests/FunctionalTestCaseTest.pm0000644000175000017500000004055710460672600017017 00000000000000package tests::FunctionalTestCaseTest; use strict; use base qw/Test::Unit::TestSuite/; sub name { return "Lire::Test::FunctionalTestCase Tests"; } sub include_tests { return qw/tests::FunctionalTestCaseTest::init tests::FunctionalTestCaseTest::api /; } package tests::FunctionalTestCaseTest::base; use strict; use base qw/Lire::Test::TestCase/; use Lire::Config::Build qw/ ac_info ac_path /; use Lire::Utils qw/ tempdir create_file file_content /; use Cwd 'realpath'; use File::Basename; use File::Path; sub set_up_fake_lire_installation { my $self = $_[0]; $self->{'testdir'} = realpath( dirname( __FILE__)); $self->{'lire_root'} = tempdir( "lire_XXXXXX", 'CLEANUP' => 1 ); $self->{'saved_build_infos'} = \%Lire::Config::Build::ac; %Lire::Config::Build::ac = ( %{$self->{'saved_build_infos'}}, 'bindir' => "$self->{'lire_root'}/bin", 'sysconfdir' => "$self->{'lire_root'}/etc", 'PACKAGE' => 'lire', 'datadir' => "$self->{'lire_root'}/share", 'LR_PERL5LIB' => "$self->{'testdir'}/..", ); mkpath( [ "$self->{'lire_root'}/etc/lire", "$self->{'lire_root'}/bin", "$self->{'lire_root'}/libexec/lire", "$self->{'lire_root'}/share/lire/config-spec", "$self->{'lire_root'}/share/lire/schemas", "$self->{'lire_root'}/share/lire/filters", "$self->{'lire_root'}/share/lire/reports", ], 0, 0755 ); create_file( "$self->{'lire_root'}/bin/lr_xml2report", "#!/bin/sh -e\ntrue" ); chmod 0755, "$self->{'lire_root'}/bin/lr_xml2report" or $self->error( "chmod on lr_xml2report failed: $!\n" ); create_file( "$self->{'lire_root'}/etc/lire/defaults", "#!/bin/sh -e\ntrue" ); create_file( "$self->{'lire_root'}/share/lire/config-spec/lire.xml", file_content( "$self->{'testdir'}/../config-spec/lire.xml" )); return; } sub tear_down_fake_lire_installation { my $self = $_[0]; %Lire::Config::Build::ac = %{$self->{'saved_build_infos'}}; return; } package tests::FunctionalTestCaseTest::init; use base qw/tests::FunctionalTestCaseTest::base/; use Lire::Config; use Lire::PluginManager; use Lire::Test::FunctionalTestCase; use Lire::Utils qw/tempfile/; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->set_up_fake_lire_installation(); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->tear_down_fake_lire_installation(); return; } sub test_new { my $self = $_[0]; my $test = new Lire::Test::FunctionalTestCase(); $self->assert_isa( 'Lire::Test::FunctionalTestCase', $test ); chmod 0000, "$self->{'lire_root'}/bin/lr_xml2report" or $self->error( "failed to remove permissions on lr_xml2report: $!" ); $self->assert_dies( qr/isn't an executable. Was Lire installed?/, sub { new Lire::Test::FunctionalTestCase() }); chmod 0755, "$self->{'lire_root'}/bin/lr_xml2report" or $self->error( "failed to put back permissions on lr_xml2report: $!" ); chmod 0000, "$self->{'lire_root'}/etc/lire/defaults" or $self->error( "failed to remove permissions on defaults: $!" ); $self->assert_dies( qr/isn't present. Was Lire installed\?/, sub { new Lire::Test::FunctionalTestCase() } ); chmod 0664, "$self->{'lire_root'}/etc/lire/defaults" or $self->error( "failed to put back permission on defaults: $!" ); foreach my $d ( "$self->{'lire_root'}/etc/lire", "$self->{'lire_root'}/share/lire" ) { chmod 0555, $d or $self->error( "failed to remove permissions on $d: $!" ); $self->assert_dies( qr/you need write access to Lire's.*$d/, sub { new Lire::Test::FunctionalTestCase() } ); chmod 0755, "$d" or $self->error( "failed to remove permissions on $d: $!" ); } } sub test_set_up { my $self = $_[0]; my @or_inc = @INC; my $test = new Lire::Test::FunctionalTestCase(); $test->set_up(); foreach my $a ( qw/_rundir _stdout_file _stderr_file _homedir/ ) { $self->assert_not_null( $test->{$a}, "set_up() should set $a" ); } foreach my $d ( qw/_rundir _homedir/ ) { $self->assert( -d $test->{$d}, "$d '$test->{$d}' wasn't created" ); } foreach my $d ( qw/ reports schemas filters config converters plugins / ) { my $dir = $test->{'_homedir'} . "/.lire/$d"; $self->assert( -d $dir, "directory '$dir' wasn't created" ); } $self->assert( -f "$test->{'_homedir'}/.lire/config/func_test_sendmail.xml", "Configuration file for fake sendmail not created." ); my ( $fh, $filename ) = tempfile( "testXXXXXX" ); push @{$test->{'_test_files'}}, $filename; $self->assert_num_equals( @or_inc + 1, scalar @INC ); $self->assert_str_equals( "$self->{'testdir'}/..", $INC[0] ); $test->tear_down(); foreach my $d ( qw/_rundir _homedir/ ) { $self->assert( !-d $test->{$d}, "$d '$test->{$d}' wasn't deleted by tear_down" ); } $self->assert( !-f $filename, "$filename should have been deleted" ); $self->assert_deep_equals( \@or_inc, \@INC ); } sub test_set_up_lire_globals { my $self = $_[0]; my $home = $ENV{'HOME'}; my $config = $Lire::Config::SINGLETON; my $mgr = $Lire::PluginManager::instance; my $test = new Lire::Test::FunctionalTestCase(); $test->{'_homedir'} = 'mydir'; $test->_set_up_lire_globals(); $self->assert_isa( 'Lire::Config::XMLFilesConfig', $Lire::Config::SINGLETON ); $self->assert_isa( 'Lire::PluginManager', $Lire::PluginManager::instance ); $self->assert_str_equals( $mgr, $test->{'_old_mgr'} ); $self->assert_str_equals( $config, $test->{'_old_config'} ); $self->assert_str_not_equals( $config, $Lire::Config::SINGLETON ); $self->assert_str_not_equals( $mgr, $Lire::PluginManager::instance ); $self->assert_str_equals( 'mydir', $ENV{'HOME'} ); $self->assert_str_equals( $home, $test->{'_old_homedir'} ); $test->_tear_down_lire_globals(); $self->assert_str_equals( $config, $Lire::Config::SINGLETON ); $self->assert_str_equals( $mgr, $Lire::PluginManager::instance ); $self->assert_str_equals( $home, $ENV{'HOME'} ); } package tests::FunctionalTestCaseTest::api; use base qw/tests::FunctionalTestCaseTest::base/; use Lire::Config::Build qw/ ac_info ac_path /; use Lire::Utils qw/file_content/; use Lire::Test::FunctionalTestCase; sub set_up { my $self = $_[0]; $self->set_up_fake_lire_installation(); $self->{'functional'} = new Lire::Test::FunctionalTestCase(); $self->{'functional'}->set_up(); } sub tear_down { my $self = $_[0]; $self->tear_down_fake_lire_installation(); $self->{'functional'}->tear_down(); } sub test_lire_run { my $self = $_[0]; $self->assert_dies( qr/missing 'cmd' parameter/, sub { $self->{'functional'}->lire_run() } ); my $result = $self->{'functional'}->lire_run( "echo This is a test" ); $self->assert_isa( "Lire::Test::CommandResult", $result ); $self->assert_equals( 0, $result->status() ); $self->assert_equals( "This is a test\n", $result->stdout() ); $self->assert( !$result->stderr(), "stderr should be empty" ); $result = $self->{'functional'}->lire_run( 'echo $PATH' ); $self->assert_equals( 0, $result->status() ); my $bindir = ac_info( 'bindir' ); $self->assert_matches( qr/^$bindir/, $result->stdout() ); } sub test_locale { my $self = $_[0]; $self->assert_str_equals( 'C', $self->{'functional'}{'_locale'} ); my $rv = $self->{'functional'}->locale( 'fr' ); $self->assert_str_equals( 'C', $rv ); $self->assert_str_equals( 'fr', $self->{'functional'}{'_locale'} ); $rv = $self->{'functional'}->locale(); $self->assert_str_equals( 'fr', $rv ); $self->assert_str_equals( 'C', $self->{'functional'}{'_locale'} ); } sub test_lire_run_locale { my $self = $_[0]; my $cmd = 'echo LANG=$LANG LC_ALL=$LC_ALL LANGUAGE=$LANGUAGE'; my $result = $self->{'functional'}->lire_run( $cmd ); $self->assert_str_equals( "LANG= LC_ALL=C LANGUAGE=\n", $result->stdout() ); $self->{'functional'}->locale( 'fr' ); $result = $self->{'functional'}->lire_run( $cmd ); $self->assert_str_equals( "LANG= LC_ALL=fr LANGUAGE=\n", $result->stdout() ); } sub test_create_test_file { my $self = $_[0]; my $file = $self->{'functional'}->rundir() . "/test_file"; my $content = <{'functional'}->create_test_file( $file, $content ); $self->assert( -f $file, "file $file doesn't exist" ); $self->assert( grep { $_ eq $file } @{$self->{'functional'}{'_test_files'}}, "$file wasn't added to _test_files" ); $self->assert_equals( $content, file_content( $file ) ); ; $self->assert_dies( qr/file already exists:/, sub { $self->{'functional'}->create_test_file( $file, $content ) }); ; $self->assert_dies( qr/missing 'filename' parameter/, sub { $self->{'functional'}->create_test_file() } ); my $empty_file = $self->{'functional'}->rundir() . "/empty_file"; $self->{'functional'}->create_test_file( $empty_file ); $self->assert( -f $empty_file, "file $empty_file wasn't created" ); $self->assert( ! -s $empty_file, "$empty_file isn't empty" ); } sub test_install_xml_spec { my $self = $_[0]; my $mock_file = $self->{'functional'}->rundir() . "/test-mock.xml"; open my $fh, "> $mock_file" or $self->error( "can't create $mock_file in rundir: $!" ); print $fh <assert_dies( qr/invalid spec_type parameter/, sub { $self->{'functional'}->install_xml_spec( "bad_param" ) } ); my $base_site = ac_path( "datadir", "PACKAGE" ); $self->{'functional'}->install_xml_spec( "site_filter", "func_test", $mock_file ); $self->assert( -f $base_site . "/filters/func_test/test-mock.xml", "file wasn't installed properly as site_filter" ); $self->{'functional'}->install_xml_spec( "site_report", "func_test", $mock_file ); $self->assert( -f $base_site . "/reports/func_test/test-mock.xml", "file wasn't installed properly as site_report" ); $self->{'functional'}->install_xml_spec( "site_schema", "test", $mock_file ); $self->assert( -f $base_site . "/schemas/test-mock.xml", "file wasn't installed properly as site_schema" ); foreach my $f ( qw!filters/func_test/test-mock.xml reports/func_test/test-mock.xml schemas/test-mock.xml ! ) { my $file = "$base_site/$f"; my $found = grep { $_ eq $file } @{$self->{'functional'}{'_test_files'}}; $self->assert( $found, "file $file wasn't added to list of files to remove" ); } my $base_home = $self->{'functional'}->homedir() . "/.lire"; $self->{'functional'}->install_xml_spec( "filter", "func_test", $mock_file ); $self->assert( -f $base_home . "/filters/func_test/test-mock.xml", "file wasn't installed properly as filter" ); $self->{'functional'}->install_xml_spec( "report", "func_test", $mock_file ); $self->assert( -f $base_home . "/reports/func_test/test-mock.xml", "file wasn't installed properly as report" ); $self->{'functional'}->install_xml_spec( "schema", "tes", $mock_file ); $self->assert( -f $base_home . "/schemas/test-mock.xml", "file wasn't installed properly as schema" ); foreach my $f ( qw!filters/func_test/test-mock.xml reports/func_test/test-mock.xml schemas/test-mock.xml ! ) { my $file = "$base_home/$f"; my $found = grep { $_ eq $file } @{$self->{'functional'}{'_test_files'}}; $self->assert( $found, "file $file wasn't added to list of files to remove" ); } } sub test_config_spec { my $self = $_[0]; my $spec = $self->{'functional'}->config_spec(); $self->assert_isa( 'Lire::Config::ConfigSpec', $spec ); } sub test_setup_sendmail_path { my $self = $_[0]; my $config_file = $self->{'functional'}->homedir() . "/.lire/config/func_test_sendmail.xml"; $self->assert_not_null( $self->{'functional'}{'_config_files'}{'func_test_sendmail'}, "no config file 'func_test_sendmail' was created" ); my $conf = $self->{'functional'}{'_config_files'}{'func_test_sendmail'}; my $e_sendmail = $self->{'functional'}->rundir() . "/func_test_sendmail"; my $sendmail_path = $conf->global->get( 'sendmail_path' )->as_value(); $self->assert_not_null( $sendmail_path, "sendmail_path wasn't set" ); $self->assert_equals( $e_sendmail, $sendmail_path ); $self->assert( -x $sendmail_path, "$sendmail_path isn't executable" ); # Make sure only one var was set foreach my $var ( $conf->global()->spec()->components() ) { next if $var->name eq 'sendmail_path'; $self->assert( ! $conf->global()->is_set( $var->name() ), $var->name() . " was set in $config_file" ); } my $maildir = $self->{'functional'}->rundir() . "/.func_test_mail"; $self->assert( -d $maildir, "directory to store sent mail doesn't exists: $maildir" ); } sub test_sent_mail { my $self = $_[0]; my $content = <{'functional'}->rundir() . "/func_test_sendmail"; open my $fh, "| $sendmail_path test1 test.2 test2" or $self->error( "open $sendmail_path failed: $!" ); print $fh $content; close $fh or $self->error( "close failed: $!" ); open $fh, "| $sendmail_path recipient1 recipient2" or $self->error( "open $sendmail_path failed: $!" ); print $fh $content; close $fh or $self->error( "close failed: $!" ); my $msg = $self->{'functional'}->sent_mail(); $self->assert_equals( 2, scalar @$msg ); for my $idx ( 0..1 ) { $self->assert_not_null( $msg->[$idx], "Message $idx structure is undef"); $self->assert_not_null( $msg->[$idx]{'recipients'}, "Message $idx 'recipients' is undef"); $self->assert_not_null( $msg->[$idx]{'message'}, "Message $idx 'message' is undef"); $self->assert_equals( 2, scalar (keys %{$msg->[$idx]}) ); } $self->assert_deep_equals( [ qw/test1 test.2 test2/ ], $msg->[0]{'recipients'} ); $self->assert_deep_equals( [ qw/recipient1 recipient2/ ], $msg->[1]{'recipients'} ); $self->assert_equals( $content, $msg->[0]{'message'} ); $self->assert_equals( $content, $msg->[1]{'message'} ); $self->assert_deep_equals( $msg, $self->{'functional'}->sent_mail() ); my $result = $self->{'functional'}->lire_run( "true" ); $self->assert_equals( 0, scalar @{$result->sent_mail() } ); $self->assert_deep_equals( $result->sent_mail(), $self->{'functional'}->sent_mail() ); } sub test_create_cfg_file { my $self = $_[0]; $self->assert_dies( qr/missing 'name' parameter/, sub { $self->{'functional'}->create_test_cfg_file() } ); $self->assert_dies( qr/'name' parameter should only contains digits, letters/, sub { $self->{'functional'}->create_test_cfg_file( "../test" ) } ); my $cfg = $self->{'functional'}->create_test_cfg_file( "test" ); $self->assert_isa( 'Lire::Config::ConfigFile', $cfg ); my $cfg_file = $self->{'functional'}->homedir() . "/.lire/config/test.xml"; $self->assert_equals( $cfg_file, $cfg->filename() ); $self->assert( ! -f $cfg_file, "$cfg_file shouldn't exist" ); $self->assert_not_null( $cfg->global(), "config's global section wasn't initialzied" ); $self->assert_equals($cfg->global()->spec(), $self->{'functional'}->config_spec() ); $self->assert_equals( $cfg, $self->{'functional'}->create_test_cfg_file( "test" )); my $result = $self->{'functional'}->lire_run( "echo Hi" ); $self->assert( -f $cfg_file, "$cfg_file wasn't created" ); } 1; lire-2.1.1/all/lib/tests/LrMissingCasesTest.pm0000644000175000017500000000141210460672577016147 00000000000000package tests::LrMissingCasesTest; use strict; use base qw/Lire::Test::TestCase/; use Lire::SQLExt::LrMissingCases; sub set_up { my $self = shift()->SUPER::set_up(); $self->{'lr_missing_cases'} = new Lire::SQLExt::LrMissingCases(); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub test_lr_missing_cases { my $self = $_[0]; my $mc = $self->{'lr_missing_cases'}; $self->assert_equals( 0, $mc->{'_count'} ); $mc->step( undef ); $self->assert_equals( 1, $mc->{'_count'} ); $mc->step( 'a' ); $self->assert_equals( 1, $mc->{'_count'} ); $mc->step( 'a', undef, 'b', 1, undef ); $self->assert_equals( 2, $mc->{'_count'} ); $self->assert_equals( 2, $mc->finalize() ); } 1; lire-2.1.1/all/lib/tests/OutputFormatsExcel95Test.pm0000644000175000017500000000442610460672601017250 00000000000000package tests::OutputFormatsExcel95Test; use strict; use base qw/Lire::Test::PluginTestCase/; use Lire::OutputFormats::Excel95; use Lire::PluginManager; use Lire::Utils qw/tempdir create_file/; use File::Basename qw/dirname/; use File::Path qw/rmtree /; use Lire::Test::Mock; sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'testdir'} = dirname( __FILE__ ) ; $self->{'tmpdir'} = tempdir( $self->name() . '_XXXXXX' ); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); Lire::Test::Mock->reset_factories(); rmtree( $self->{'tmpdir'} ); return; } sub create_plugin { return new Lire::OutputFormats::Excel95(); } sub registration_file { return dirname( __FILE__ ) . "/../Lire/OutputFormats/of_excel95_init"; } sub test_format_report { my $self = $_[0]; $self->test_registration_file(); Lire::Test::Mock->set_mock_factory( 'Lire::ReportParser::ExcelWriter', 'parsefile' => sub { create_file( shift->{'_output_file'} ) } ); my $excel95 = Lire::PluginManager->get_plugin( 'output_format', 'excel95'); my $report = "$self->{'tmpdir'}/report.xls"; $excel95->format_report( "$self->{'testdir'}/data/test-sqlite.xml", $report ); my ($writer) = @{Lire::Test::Mock->mock_instances( 'Lire::ReportParser::ExcelWriter' )}; my ( $pkg, %args ) = @{$writer->get_invocation( 'new' )}; $self->assert_str_equals( $report, $args{'output_file'} ); $self->assert_num_equals( 1, $writer->invocation_count( 'parsefile' ) ); } sub test_mime_report { my $self = $_[0]; $self->test_registration_file(); Lire::Test::Mock->set_mock_factory( 'Lire::ReportParser::ExcelWriter', 'parsefile' => sub { create_file( shift->{'_output_file'} ) } ); my $excel95 = Lire::PluginManager->get_plugin( 'output_format', 'excel95' ); my $entity = $excel95->mime_report( "$self->{'testdir'}/data/test-sqlite.xml" ); $self->assert_isa( 'MIME::Entity', $entity ); $self->assert_str_equals( 'application/vnd.ms-excel', $entity->head()->mime_type() ); $self->assert_str_equals( "base64\n", $entity->head()->get( 'content-transfer-encoding' ) ); } 1; lire-2.1.1/all/lib/tests/ExtendedSchemaTest.pm0000644000175000017500000002173510460672600016137 00000000000000package tests::ExtendedSchemaTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::DlfSchema; use Lire::ExtendedSchema; use Lire::DerivedSchema; use Lire::Field; use Lire::DlfStore; use Lire::Utils qw/tempdir/; use File::Basename qw/dirname/; use Cwd qw/realpath/; sub new { my $self = shift()->SUPER::new( @_ ); $self->{'tmpdir'} = tempdir( __PACKAGE__ . "XXXXXX", 'TMPDIR' => 1, CLEANUP => 1 ); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'old_cache'} = { %Lire::DlfSchema::SCHEMA_CACHE }; %Lire::DlfSchema::SCHEMA_CACHE = (); # Make sure the Lire::DlfSchema can find our test schemas. $self->{'cfg'}{'lr_schemas_path'} = [ realpath( dirname(__FILE__) . "/schemas" ) ]; $self->{'schema'} = Lire::DlfSchema::load_schema( "test-extended" ); $self->{'cfg'}{'_lr_config_spec'} = $self->lire_default_config_spec(); # We don't open the store in new() because we need to # change the configuration before $self->{'store'} = Lire::DlfStore->open( "$self->{'tmpdir'}/store", 1 ) unless defined $self->{'store'}; return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->{'store'}->_dbh()->rollback(); %Lire::DlfSchema::SCHEMA_CACHE = %{$self->{'old_cache'}}; return; } sub test_new { my $self = $_[0]; $self->assert_dies( qr/cannot find superservice in id: test_extended/, sub { new Lire::ExtendedSchema( 'id' => 'test_extended' ) } ); $self->assert_dies( qr/base schema cannot be an extended schema: test-extended/, sub { new Lire::ExtendedSchema( 'id' => 'test-another', 'base-schema' => 'test-extended' ) } ); my $schema = new Lire::ExtendedSchema( 'id' => 'test-extended', 'module' => 'MyModule', 'base-schema' => 'test' ); $self->assert_isa( 'Lire::ExtendedSchema', $schema ); $self->assert_str_equals( 'test-extended', $schema->{'id'} ); $self->assert_str_equals( 'test', $schema->{'superservice'} ); my $base = Lire::DlfSchema::load_schema( 'test' ); $self->assert_str_equals( $base, $schema->{'base'} ); $self->assert_deep_equals( [ $base->fields() ], $schema->{'fields_by_pos'} ); $self->assert_deep_equals( $base->{'fields_by_name'}, $schema->{'fields_by_name'} ); $self->assert_num_equals( 11, $schema->{'extended_start_idx'} ); } sub test_id { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); $self->assert_str_equals( "test-extended", $self->{'schema'}->id() ); } sub test_superservice { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); $self->assert_str_equals( "test", $self->{'schema'}->superservice() ); } sub test_base { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); my $base = $self->{'schema'}->base(); $self->assert_isa( 'Lire::DlfSchema', $base ); $self->assert_str_equals( "test", $base->id() ); } sub test_extended_fields { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); my $mockfield = bless { 'name' => 'dirname', 'type' => 'filename', 'pos' => 11, 'description' => "\n Contains the file's directory.\n ", 'label' => 'Directory', 'i18n_domain' => 'lire-test', }, 'Lire::Field'; $self->assert_deep_equals( [ $mockfield ], $self->{'schema'}->extended_fields() ); } sub test_can_join_schema { my $self = $_[0]; my $test = new Lire::DlfSchema( 'superservice' => 'test', 'timestamp' => 'time' ); $test->add_field( new Lire::Field( 'name' => 'time', 'type' => 'timestamp' ) ); $Lire::DlfSchema::SCHEMA_CACHE{'test'} = $test; my $test2 = new Lire::DlfSchema( 'superservice' => 'test2', 'timestamp' => 'time' ); $test2->add_field( new Lire::Field( 'name' => 'time', 'type' => 'timestamp' ) ); $Lire::DlfSchema::SCHEMA_CACHE{'test2'} = $test2; my $ext1 = new Lire::ExtendedSchema( 'id' => 'test-ext1', 'base-schema' => 'test', 'module' => 'MyModule' ); my $ext2 = new Lire::ExtendedSchema( 'id' => 'test2-ext2', 'base-schema' => 'test2', 'module' => 'MyModule' ); my $ext3 = new Lire::ExtendedSchema( 'id' => 'test-ext3', 'base-schema' => 'test', 'module' => 'MyModule' ); my $derived = new Lire::DerivedSchema( 'id' => 'test-derived', 'base-schema' => 'test', 'timestamp' => 'time', 'module' => 'MyModule' ); $self->assert( $ext1->can_join_schema( $ext3 ) ); $self->assert( ! $ext1->can_join_schema( $test ) ); $self->assert( ! $ext1->can_join_schema( $ext1 ) ); $self->assert( ! $ext1->can_join_schema( $ext2 ) ); $self->assert( ! $ext1->can_join_schema( $test2 ) ); $self->assert( ! $ext1->can_join_schema( $derived ) ); } sub test_sql_insert_query { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); my $e_sql = q{INSERT INTO "dlf_test-extended" (dlf_id, dlf_source, dirname) VALUES (?,?,?)}; $self->assert_str_equals( $e_sql, $self->{'schema'}->sql_insert_query() ); } sub test_create_sql_schema { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); $self->{'schema'}->create_sql_schema( $self->{'store'} ); my $sql_def = $self->{'schema'}->_sql_fields_def(); chomp $sql_def; # Trailing newline removed by SQLite my $dbh = $self->{'store'}->_dbh(); my $table = $dbh->selectrow_hashref( "SELECT * FROM sqlite_master WHERE name = 'dlf_test-extended'" ); $self->assert_not_null( $table, "table dlf_test wasn't created" ); $self->assert_matches( qr/\Q$sql_def\E/, $table->{'sql'} ); my $index = $dbh->selectrow_hashref( "SELECT * FROM sqlite_master WHERE name = 'dlf_test-extended_time_start_idx'" ); $self->assert_null( $index, "index shouldn't exists" ); my $trigger = $dbh->selectrow_hashref( q{SELECT * FROM sqlite_master WHERE name = 'dlf_test-extended_delete_trigger'} ); $self->assert_not_null( $trigger, "trigger dlf_test-extended_delete_trigger wasn't created" ); $self->assert_str_equals( "trigger", $trigger->{'type'} ); my $trigger_sql = <assert_str_equals( $trigger_sql, $trigger->{'sql'} ); } sub test_sql_clean_query { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); $self->assert_str_equals( 'DELETE FROM "dlf_test-extended"', $self->{'schema'}->sql_clean_query() ); $self->{'schema'}{'timestamp_field'} = 'time-start'; $self->assert_str_equals( 'DELETE FROM "dlf_test-extended" WHERE dlf_id IN ( SELECT e.dlf_id FROM dlf_test b, "dlf_test-extended" e WHERE b.dlf_id = e.dlf_id AND "b.time-start" < ? )', $self->{'schema'}->sql_clean_query( 1 ) ); } sub test_sql_clean_period_query { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); $self->{'schema'}{'timestamp_field'} = 'time-start'; $self->assert_str_equals( 'DELETE FROM "dlf_test-extended" WHERE dlf_id IN ( SELECT e.dlf_id FROM dlf_test b, "dlf_test-extended" e WHERE b.dlf_id = e.dlf_id AND "b.time-start" >= ? AND "b.time-start" < ? )', $self->{'schema'}->sql_clean_period_query ); } sub test_dlf_query { my $self = $_[0]; my $query = $self->{'schema'}->dlf_query( 'time_start' ); $self->assert_isa( 'Lire::DlfQuery', $query ); $self->assert( $query->has_field( 'dlf_id' ), 'missing dlf_id' ); $self->assert_str_equals( '"dlf_test-extended".dlf_id', $query->field_def( 'dlf_id' ) ); $self->assert( $query->has_field( 'dlf_source' ), 'missing dlf_source' );; $self->assert_str_equals( '"dlf_test-extended".dlf_source', $query->field_def( 'dlf_source' ) ); $self->assert( $query->has_field( 'dirname' ), 'missing dirname' ); $self->assert_str_equals( 'time_start', $query->sort_spec() ); return; } 1; lire-2.1.1/all/lib/tests/ConfigValuesTest.pm0000644000175000017500000004441310460672600015641 00000000000000package tests::ConfigValuesTest; use strict; use base qw/Test::Unit::TestSuite/; use Lire::Config::TypeSpec; use Lire::Config::Value; use IO::Scalar; sub name { return "Configuration Values Tests"; } sub include_tests { return qw/tests::ConfigScalarTest tests::ConfigListTest tests::ConfigDictionaryTest /; } package tests::ConfigValueTest; use base qw/Lire::Test::TestCase/; sub new { my $self = shift->SUPER::new( @_ ); $self->{'config_spec'} = new Lire::Config::ConfigSpec(); $self->{'list_spec'} = new Lire::Config::ListSpec( 'name' => "list" ); $self->{'config_spec'}->add( $self->{'list_spec'} ); $self->{'int_spec'} = new Lire::Config::IntegerSpec( 'name' => "int" ); $self->{'config_spec'}->add( $self->{'int_spec'} ); $self->{'string_spec'} = new Lire::Config::StringSpec( 'name' => "string" ); $self->{'config_spec'}->add( $self->{'string_spec'} ); $self->{'list_spec'}->add( $self->{'int_spec'} ); $self->{'select_spec'} = new Lire::Config::SelectSpec( 'name' => "select" ); $self->{'config_spec'}->add( $self->{'select_spec'} ); $self->{'list_spec'}->add( $self->{'select_spec'} ); $self->{'select_spec'}->add( new Lire::Config::OptionSpec( 'name' => "option_1" )); $self->{'select_spec'}->add( new Lire::Config::OptionSpec( 'name' => "option_2" )); return $self; } sub test_new { my $self = $_[0]; my $value = $self->type()->new( 'spec' => $self->spec() ); $self->assert_isa( $self->type(), $value ); $self->assert_str_equals( $self->spec()->name(), $value->name() ); my $proto = $value->new(); $self->assert_isa( $self->type(), $proto ); $self->assert_str_not_equals( $proto, $value ); $self->assert_deep_equals( $proto, $value ); $self->assert_dies( qr/missing 'spec' parameter/, sub { $self->type()->new() } ); $self->assert_dies( qr/'spec' parameter.*should be a.*instance/, sub { $self->type()->new( 'spec' => $self ) } ); } sub test_as_shell_var { my $self = $_[0]; my $value = $self->type()->new( 'spec' => $self->spec() ); my $name = $value->name(); $self->assert_matches( qr/$name=.*not supported/, $value->as_shell_var() ); } sub test_clone { my $self = $_[0]; my $value = $self->type()->new( 'spec' => $self->spec() ); my $clone = $value->clone(); $self->assert_str_not_equals( $value, $clone ); $self->assert_deep_equals( $value, $clone ); $self->assert_str_equals( $value->{'spec'}, $clone->{'spec'} ); } sub test_is_equals { my $self = $_[0]; my $value = $self->type()->new( 'spec' => $self->spec() ); $self->assert( $value->is_equals( $value ), 'is_equals( $self )' ); $self->assert( $value->is_equals( $value->clone() ), 'is_equals( clone )' ); # Changing the spec, should returns false. my $other_value = $value->clone(); $other_value->{'spec'} = {}; $self->assert( ! $value->is_equals( $other_value ), '! is_equals( other_spec )' ); } sub test_is_default { my $self = $_[0]; my $default = $self->spec()->instance(); $self->assert( ! $default->is_default(), "!is_default()" ); $self->spec()->default( $default ); my $value = $self->type()->new( 'spec' => $self->spec() ); $self->assert( $value->is_default(), "is_default() != 1" ); } sub check_save_xml_default { my ( $self, $value ) = @_; my $name = $self->spec()->name(); my $fh = new IO::Scalar(); my $buf = $fh->sref(); $value->save_xml( $fh ); my $pos = index( $$buf, "assert( $pos >= 0, $$buf || 'Nothing written' ); $self->spec()->default( $value ); my $default = $self->spec()->instance(); $$buf = ''; $default->save_xml( $fh ); $self->assert_str_equals( '', $$buf ); $self->spec()->default( undef ); } sub check_save_xml_obsolete { my ( $self, $value ) = @_; my $name = $self->spec()->name(); my $fh = new IO::Scalar(); my $buf = $fh->sref(); $self->spec()->obsolete( 1 ); $value->save_xml( $fh ); $self->assert_str_equals( '', $$buf ); $self->spec()->obsolete( 0 ); $value->save_xml( $fh, 0, 'lrcml:' ); my $pos = index( $$buf, "assert( $pos >= 0, $$buf || 'Nothing written' ); } sub test_save_xml { my $self = $_[0]; my $value = $self->spec()->instance(); $self->check_save_xml_default( $value->clone() ); $self->check_save_xml_obsolete( $value->clone() ); } package tests::ConfigScalarTest; use base qw/tests::ConfigValueTest/; sub type { return "Lire::Config::Scalar"; } sub spec { return $_[0]{'int_spec'}; } sub test_new { my $self = $_[0]; $self->SUPER::test_new; my $value = new Lire::Config::Scalar( 'spec' => $self->{'int_spec'}, 'value' => 10, ); $self->assert_equals( 10, $value->as_value() ); $self->assert_deep_equals( $value, $value->new() ); my $other = $value->new( 'value' => 11 ); $self->assert_num_equals( 11, $other->{'value'} ); } sub test_as_value { my $self = $_[0]; my $value = new Lire::Config::Scalar( 'spec' => $self->{'int_spec'} ); $value->set( 10 ); $self->assert_equals( 10, $value->as_value() ); $value = new Lire::Config::Scalar( 'spec' => $self->{'select_spec'} ); $value->set( "OPTION_1" ); $self->assert_equals( "OPTION_1", $value->get() ); $self->assert_equals( "option_1", $value->as_value() ); my $warning = ''; local $SIG{'__WARN__'} = sub { $warning .= join "", @_ }; $value = new Lire::Config::Scalar( 'spec' => $self->{'select_spec'} ); $value->{'value'} = "no_such_option"; my @array_context = $value->as_value(); $self->assert_matches( qr/invalid value for parameter 'select':/, $warning ); $self->assert_deep_equals( [], \@array_context ); # Second as_value() shouldn't emit another warning $warning = ''; $self->assert_null( scalar $value->as_value(), "should return undef in scalar context" ); $self->assert_equals( '', $warning ); } sub test_as_shell_var { my $self = $_[0]; my $int = $self->type->new( 'spec' => $self->{'int_spec'}, value => 10 ); $self->assert_equals( "int='10'", $int->as_shell_var() ); my $undefined_int = $self->type->new( 'spec' => $self->{'int_spec'} ); $self->assert_equals( "", $undefined_int->as_shell_var() ); my $s = q{> Long string with shell `metacharacters`, 'quote', "double"}; my $quoted = q{> Long string with shell `metacharacters`, '\''quote'\'', "double"}; my $string = $self->type->new( 'spec' => $self->{'string_spec'}, value => $s ); $self->assert_equals( "string='$quoted'", $string->as_shell_var() ); local $SIG{'__WARN__'} = sub { $self->annotate( join "", @_ ) }; my $bad_option = $self->type->new( 'spec' => $self->{'select_spec'}, 'value' => "bad_option" ); $self->assert_equals( '', $bad_option->as_shell_var() ); } sub test_set { my $self = $_[0]; my $value = new Lire::Config::Scalar( 'spec' => $self->{'int_spec'} ); $value->set( 10 ); $self->assert_equals( 10, $value->get() ); my $warning = undef; my $oldwarn = $SIG{'__WARN__'}; $SIG{'__WARN__'} = sub { $warning = join(' ', @_); }; $value->set('file'); $SIG{'__WARN__'} = $oldwarn; $self->assert_null($warning, "set() with invalid value should NOT warn"); } sub test_is_equals { my $self = $_[0]; $self->SUPER::test_is_equals(); my $string = new Lire::Config::Scalar( 'spec' => $self->{'string_spec'} ); my $other_string = $string->clone(); $string->{'value'} = 'A value'; my $int = new Lire::Config::Scalar( 'spec' => $self->{'int_spec'} ); my $other_int = $int->clone(); $int->{'value'} = 10; $self->assert( ! $string->is_equals( $other_string ), "! is_equals( undef )" ); $other_int->{'value'} = 11; $self->assert( ! $int->is_equals( $other_int ), "! is_equals( 11 )" ); $other_int->{'value'} = "10.0000"; $self->assert( $int->is_equals( $other_int ), "is_equals( 10.00 )" ); } package tests::ConfigListTest; use base qw/tests::ConfigValueTest/; sub type { return "Lire::Config::List"; } sub spec { return $_[0]{'list_spec'}; } sub test_new { my $self = $_[0]; $self->SUPER::test_new(); my $list = $self->{'list_spec'}->instance(); $list->append( $self->{'select_spec'}->instance() ); $self->assert_deep_equals( $list, $list->new() ); } sub test_as_value { my $self = $_[0]; local $SIG{'__WARN__'} = sub { $self->annotate( join "", @_ ) }; my $list = $self->{'list_spec'}->instance(); $self->assert_deep_equals( [], $list->as_value() ); $list->append( $self->{'int_spec'}->instance( 'value' => 10 ) ); $list->append( $self->{'select_spec'}->instance( 'value' => "option_1" ) ); $list->append( $self->{'select_spec'}->instance( 'value' => "no_such_option" ) ); $self->assert_deep_equals( [ 10, "option_1" ], $list->as_value(), ); } sub test_is_valid { my $self = $_[0]; my $list = $self->{'list_spec'}->instance(); $self->assert( $list->is_valid(), 'is_valid()' ); $list->append( $self->{'int_spec'}->instance( 'value' => 'abc' ) ); $self->assert( !$list->is_valid(), '!is_valid()' ); $list->get( 0 )->set( '10' ); $self->assert( $list->is_valid(), 'is_valid()' ); $list->append( $self->{'select_spec'}->instance( 'value' => "bad_option")); $self->assert( !$list->is_valid(), '!is_valid()' ); $list->get( 1 )->spec()->required( 0 ); $self->assert( $list->is_valid(), 'is_valid()' ); } sub test_get { my $self = $_[0]; my $list = $self->{'list_spec'}->instance(); $self->assert_dies( qr/index out of bounds/, sub { $list->get( 0 ) } ); my $int = $self->{'int_spec'}->instance( 'value' => 10 ); $list->append( $int ); $self->assert_equals( $int, $list->get( 0 ) ); $self->assert_equals( $int, $list->get( -1 ) ); $self->assert_dies( qr/'idx' parameter should be an integer/, sub { $list->get( "string" ) } ); } sub test_set { my $self = $_[0]; my $list = $self->{'list_spec'}->instance(); $self->assert_dies( qr/missing 'idx' parameter/, sub { $list->set() }); my $int = $self->{'int_spec'}->instance( 'value' => 10 ); $self->assert_dies( qr/index out of bounds: 0/, sub { $list->set( 0, $int ) } ); $list->append( $int ); $self->assert_dies( qr/missing 'value' parameter/, sub { $list->set( 0, undef ) } ); $int = $self->{'int_spec'}->instance( 'value' => 5 ); $list->set( 0, $int ); $self->assert_str_equals( $int, $list->{'elements'}[0] ); } sub test_append { my $self = $_[0]; my $list = $self->{'list_spec'}->instance(); $self->assert_equals( 0, scalar $list->elements() ); my $select = $self->{'select_spec'}->instance(); my $int = $self->{'int_spec'}->instance( 'value' => 10 ); $list->append( $select ); $self->assert_equals( 1, scalar $list->elements() ); $list->append( $int ); $self->assert_deep_equals( [ $select, $int ], [$list->elements()] ); $self->assert_dies( qr/missing 'value' parameter/, sub { $list->append() }); $self->assert_dies( qr/cannot contains config parameters/, sub { $list->append( $self->{'config_spec'}->instance() )}); my $bad_select = new Lire::Config::SelectSpec( 'name' => $self->{'select_spec'}->name ); $self->assert_dies( qr/is not a valid instance for component/, sub { $list->append( $bad_select->instance() ) } ); } sub test_check_idx { my $self = $_[0]; my $list = $self->{'list_spec'}->instance(); $self->assert_dies( qr/not an integer: wawa/, sub { $list->check_idx( 'wawa' ) } ); $self->assert_dies( qr/index out of bounds: 0/, sub { $list->check_idx( 0 ) } ); $self->assert_dies( qr/index out of bounds: -1/, sub { $list->check_idx( -1 ) } ); $list->{'elements'} = [ undef, undef, undef ]; foreach my $idx ( qw/ 0 1 2 -1 -2 -3/ ) { eval { $list->check_idx( $idx ) }; $self->fail( "$@" ) if $@; } } sub test_append_idx { my $self = $_[0]; my $list = $self->{'list_spec'}->instance(); my $int = $self->{'int_spec'}->instance( 'value' => 10 ); $list->{'elements'} = [ undef, undef ]; $list->append( $int, 0 ); $self->assert_deep_equals( [ undef, $int, undef ], $list->{'elements'} ); $list->append( $int, -1 ); $self->assert_deep_equals( [ undef, $int, undef, $int ], $list->{'elements'} ); } sub test_move { my $self = $_[0]; my $list = $self->{'list_spec'}->instance(); $list->{'elements'} = [ 0, 1, 2, 3, 4 ]; $list->move( 0, -1 ); $self->assert_deep_equals( [ 1, 2, 3, 4, 0 ], $list->{'elements'} ); $list->move( 1, 0 ); $self->assert_deep_equals( [ 2, 1, 3, 4, 0 ], $list->{'elements'} ); $list->move( 2, -2 ); $self->assert_deep_equals( [ 2, 1, 4, 3, 0 ], $list->{'elements'} ); $list->move( 0, 0 ); $self->assert_deep_equals( [ 2, 1, 4, 3, 0 ], $list->{'elements'} ); $list->move( 0, -5 ); $self->assert_deep_equals( [ 2, 1, 4, 3, 0 ], $list->{'elements'} ); $list->move( -5, -5 ); $self->assert_deep_equals( [ 2, 1, 4, 3, 0 ], $list->{'elements'} ); $list->move( -5, -4 ); $self->assert_deep_equals( [ 1, 2, 4, 3, 0 ], $list->{'elements'} ); } sub test_clear { my $self = $_[0]; my $list = $self->{'list_spec'}->instance(); $list->{'elements'} = [ 0, 1, 2, 3, 4 ]; $list->clear(); $self->assert_deep_equals( [], $list->{'elements'} ); } sub test_is_equals { my $self = $_[0]; $self->SUPER::test_is_equals(); my $list = $self->{'list_spec'}->instance(); my $other = $list->clone(); my $int = $self->{'int_spec'}->instance( 'value' => 10 ); $list->append( $int ); $self->assert( ! $list->is_equals( $other ), '! is_equals( count )' ); $other->append( $self->{'int_spec'}->instance( 'value' => 11 ) ); $self->assert( ! $list->is_equals( $other ), '! is_equals( different )' ); $other->set( 0, $int->clone() ); $self->assert( $list->is_equals( $other ), 'is_equals()' ); } package tests::ConfigDictionaryTest; use base qw/tests::ConfigValueTest/; sub type { return "Lire::Config::Dictionary"; } sub spec { return $_[0]{'config_spec'}; } sub test_new { my $self = $_[0]; $self->SUPER::test_new(); my $dict = $self->{'config_spec'}->instance(); $dict->set( $self->{'int_spec'}->instance() ); $self->assert_deep_equals( $dict, $dict->new() ); } sub test_as_value { my $self = $_[0]; local $SIG{'__WARN__'} = sub { $self->annotate( join "", $@ ) }; my $dict = $self->{'config_spec'}->instance(); $self->assert_deep_equals( { 'select' => undef, 'int' => 0, 'list' => [], 'string' => '', }, $dict->as_value, ); $dict->set( $self->{'select_spec'}->instance( 'value' => "option_1" ) ); $dict->set( $self->{'int_spec'}->instance( 'value' => "10" ) ); $self->assert_deep_equals( { 'select' => "option_1", 'int' => 10, 'list' => [], 'string' => '', }, $dict->as_value, ); } sub test_is_set { my $self = $_[0]; my $dict = $self->{'config_spec'}->instance(); $self->assert( !$dict->is_set( "int" ), "is_set() returned true" ); $dict->get( 'int' ); $self->assert( $dict->is_set( "int" ), "is_set() returned false" ); $self->assert_dies( qr/missing 'name' parameter/, sub { $dict->is_set() } ); ; $self->assert_dies( qr/no parameter no_such_param defined/, sub { $dict->is_set( "no_such_param") } ); } sub test_get { my $self = $_[0]; my $dict = $self->{'config_spec'}->instance(); my $int = $dict->get( "int" ); $self->assert_not_null( $int, "get() should create the instance" ); $self->assert_equals( "int", $int->name() ); $self->assert_str_equals( '', $int->get() ); $self->assert_equals( $int, $dict->get( "int" ) ); $self->assert_dies( qr/missing 'name' parameter/, sub { $dict->get() } ); $self->assert_dies( qr/no parameter bad_param defined in/, sub { $dict->get( "bad_param" ) } ); } sub test_set { my $self = $_[0]; my $dict = $self->{'config_spec'}->instance(); $self->assert_dies( qr/missing 'value' parameter/, sub { $dict->set() } ); $self->assert_dies( qr/\'value\' parameter should be a \'Lire::Config::Value\' instance, not/, sub{ $dict->set( $self->{'config_spec'} ) } ); my $int = $self->{'int_spec'}->instance(); $dict->set( $int ); $self->assert_equals( $int, $dict->get( 'int' ) ); my $select = new Lire::Config::SelectSpec( 'name' => 'int' )->instance(); ; $self->assert_dies( qr/is not a valid instance for parameter/, sub { $dict->set( $select ) } ); } sub test_is_equals { my $self = $_[0]; $self->SUPER::test_is_equals(); my $dict = $self->{'config_spec'}->instance(); my $other = $dict->clone(); $dict->set( $self->{'string_spec'}->instance( 'value' => 'A value' ) ); $self->assert( ! $dict->is_equals( $other ), "!is_equals()" ); $other->set( $self->{'string_spec'}->instance( 'value' => 'A value' ) ); $self->assert( $dict->is_equals( $other ), "is_equals()" ); } sub test_is_valid { my $self = $_[0]; my $cfg = $self->{'config_spec'}->instance(); $self->assert( !$cfg->is_valid(), '!is_valid()' ); $cfg->get( 'int' )->set( 10 ); $cfg->get( 'select' )->spec()->required( 0 ); $cfg->get( 'string' )->spec()->required( 0 ); $self->assert( $cfg->is_valid(), 'is_valid()' ); } 1; lire-2.1.1/all/lib/tests/MockAggregator.pm0000644000175000017500000000076710460672577015331 00000000000000package tests::MockAggregator; use base qw/Lire::Aggregator/; sub new { my $self = bless {}, shift; $self->SUPER::init( @_, 'op' => 'mock-aggregator' ); my %params = @_; $self->{'name'} = $params{'name'} if defined $params{'name'}; return $self; } sub name { return $_[0]{'name'} || 'mockAggregator'; } sub create_categorical_info { my ( $self, $info ) = @_; $info->create_column_info( $self->name, 'categorical', 'string', 'All records' ); } 1; lire-2.1.1/all/lib/tests/MaxTest.pm0000644000175000017500000000206210460672577014010 00000000000000package tests::MaxTest; use strict; use base qw/Lire::Test::TestCase tests::TestStoreFixture/; use Lire::Max; use Lire::ReportSpec; use tests::MockAggregator; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); return $self; } sub set_up { my $self = shift->SUPER::set_up(); $self->set_up_test_schema(); $self->{'spec'} = new Lire::ReportSpec(); $self->{'spec'}->superservice( 'test' ); $self->{'spec'}->id( 'test-max' ); my $mock = new tests::MockAggregator( 'report_spec' => $self->{'spec'} ); $self->{'max'} = new Lire::Max( 'report_spec' => $self->{'spec'}, 'parent' => $mock, 'field' => 'file_size', 'name' => 'max' ); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub test_sql_aggr_expr { my $self = $_[0]; $self->{'max'}{'field'} = 'file-size'; $self->assert_equals( 'max("file-size")', $self->{'max'}->sql_aggr_expr() ); } 1; lire-2.1.1/all/lib/tests/OutputFormatsFixture.pm0000644000175000017500000000236210460672601016615 00000000000000package tests::OutputFormatsFixture; use strict; use Lire::Config::SpecParser; use Lire::Utils qw/file_content deep_copy/; use Lire::Config::Build qw/ac_info/; use File::Basename qw/dirname/; sub set_up_output_formats { my ( $self, $new_mgr) = @_; $new_mgr = ! $self->isa( 'Lire::Test::FunctionalTestCase' ) unless defined $new_mgr; $self->set_up_plugin_mgr() if $new_mgr; my $testdir = dirname( __FILE__ ); my $formatsdir = "$testdir/../Lire/OutputFormats"; opendir my $dh, $formatsdir or $self->error( "opendir '$formatsdir' failed: $!" ); foreach my $basename ( readdir $dh ) { next unless $basename =~ /_init$/; eval file_content( "$formatsdir/$basename" ); $self->error( "error loading '$formatsdir/$basename': $@" ) if $@; } closedir $dh; my $parser = new Lire::Config::SpecParser(); unless ( $self->isa( 'Lire::Test::FunctionalTestCase' ) ) { $parser->{'_spec'} = deep_copy( $self->{'cfg'}{'_lr_config_spec'} || $self->lire_default_config_spec() ); } $parser->merge_specifications_dir( "$testdir/../Lire/OutputFormats" ); $self->{'cfg'}{'_lr_config_spec'} = $parser->configspec(); return; } 1; lire-2.1.1/all/lib/tests/ReportParserHTMLWriterTest.pm0000644000175000017500000007662010460672601017574 00000000000000package tests::ReportParserHTMLWriterTest; use strict; use base qw/ Lire::Test::TestCase tests::TestStoreFixture tests::ChartTypesFixture /; use File::Basename qw/dirname/; use Lire::ChartType; use Lire::Config::ConfigSpec; use Lire::DlfSchema; use Lire::Report; use Lire::Report::TableInfo; use Lire::Report::Section; use Lire::Report::Subreport; use Lire::ReportParser::HTMLWriter; use Lire::ReportParser::ReportBuilder; use Lire::Utils qw/ tempdir file_content /; use Lire::Test::Mock; use IO::Scalar; use File::Path qw/rmtree/; use Time::Local; #our @TESTS = qw//; sub new { my $self = shift()->SUPER::new( @_ ); $self->init(); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->set_up_test_schema(); $self->{'tmpdir'} = tempdir( $self->name() . "_XXXXXX" ); $self->set_up_tz( 'UTC' ); $self->{'writer'} = new_proxy Lire::Test::Mock( 'Lire::ReportParser::HTMLWriter' ); $self->{'writer'}{'_fh'} = new IO::Scalar(); $self->{'writer'}{'_outputdir'} = $self->{'tmpdir'}; $self->{'writer'}{'_etag'} = '>'; $self->{'writer'}{'_xhtml'} = '0'; return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down( @_ ); rmtree( $self->{'tmpdir'}, 0 ) unless $self->{'keep_tmpdir'}; no warnings 'redefine'; *Lire::ReportParser::HTMLWriter::ac_path = $self->{'_or_ac_path'} if $self->{'_or_ac_path'}; return; } sub set_up_report { my $self = $_[0]; my $report = new Lire::Report(); my $sect1 = new Lire::Report::Section( '
    ' ); my $sub1 = new Lire::Report::Subreport( 'test', 'top-dirs' ); $sub1->title( '' ); $sub1->id( 'top-dirs.0' ); $sub1->schemas( 'test-extended' ); $sect1->add_subreport( $sub1 ); $report->add_section( $sect1 ); my $sect2 = new Lire::Report::Section( 'Section 2' ); $report->add_section( $sect2 ); my $sub2 = new Lire::Report::Subreport( 'test', 'top-files' ); $sub2->title( 'Top Files 1' ); $sub2->id( 'top-files.0' ); $sub2->schemas( 'test' ); $sect2->add_subreport( $sub2 ); my $sub3 = new Lire::Report::Subreport( 'test', 'top-files' ); $sub3->title( 'Top Files 2' ); $sub3->id( 'top-files.1' ); $sub3->schemas( 'test' ); $sect2->add_subreport( $sub3 ); $self->{'report'} = $report; return; } sub set_up_subreport { my $self = $_[0]; my $subreport = new Lire::Report::Subreport( 'test', 'test1' ); my $table_info = new Lire::Report::TableInfo(); $table_info->create_column_info( 'user', 'categorical', 'string', '' ); my $group = $table_info->create_group_info( 'group1' ); $group->create_column_info( 'file', 'categorical', 'string', '' ); $group->create_column_info( 'count', 'numerical', 'int', 'Downloads' ); $group->create_column_info( 'size', 'numerical', 'bytes', 'Size' ); $table_info->compute_group_layout(); $subreport->table_info( $table_info ); $subreport->schemas( 'test' ); $self->{'subreport'} = $subreport; return; } sub set_up_subreport_data { my $self = $_[0]; my $data = [ [ 'flacoste', undef, 9, 53 ], [ undef, 'page1.html', 5, 50 ], [ undef, 'page2.html', 4, 3 ], [ '', undef, 5, 10 ], [ undef, 'page3.html', 3, 6 ], [ undef, 'page2.html', 1, 2 ], [ undef, 'page4.html', 1, 2 ] ]; my $group; foreach my $r ( @$data ) { my ( $user, $page, $count, $size ) = @$r; if ( $user ) { my $entry = $self->{'subreport'}->create_entry(); $entry->add_name( $user ); $group = $entry->create_group(); $group->set_summary_value( 'count', 'content' => $count ); $group->set_summary_value( 'size', 'content' => $size ); } else { my $entry = $group->create_entry(); $entry->add_name( $page ); $entry->add_value( 'content' => $count ); $entry->add_value( 'content' => $size ); } } $self->{'subreport'}->finalize(); return; } sub set_up_chart_configs { my $self = $_[0]; $self->{'cfg'}{'_lr_config_spec'} = new Lire::Config::ConfigSpec(); $self->set_up_plugin_mgr(); my $type = new_proxy Lire::Test::Mock( 'Lire::ChartType' ); $type->set_result( 'name' => 'mock_chart', 'write_chart' => sub { return "$self->{'tmpdir'}/chart.png" } ); Lire::PluginManager->register_plugin( $type ); $self->{'mock_chart'} = $type; $self->{'chart1'} = new Lire::Report::ChartConfig(); $self->{'chart1'}->type( $type ); $self->{'chart1'}->title( '' ); $self->{'chart2'} = new Lire::Report::ChartConfig(); $self->{'chart2'}->type( $type ); return; } sub test_write_report { my $self = $_[0]; $self->set_up_report(); my $output_dir = "$self->{'tmpdir'}/wawa"; my $writer = new_proxy Lire::Test::Mock( 'Lire::ReportParser::HTMLWriter'); $writer->set_result( 'start_page', '' ); $writer->set_result( 'end_page', '' ); $writer->set_result( 'write_toc', '' ); $writer->set_result( 'write_section', '' ); $writer->set_result( 'write_schema', '' ); $writer->set_result( 'copy_html_files', '' ); $writer->write_report( $self->{'report'}, $output_dir ); $self->assert_str_equals( $self->{'report'}, $writer->{'_report'} ); $self->assert_str_equals( $output_dir, $writer->{'_outputdir'} ); $self->assert( -d $writer->{'_outputdir'}, "directory '$writer->{'_outputdir'}' wasn't created" ); $self->assert_str_equals( ' />', $writer->{'_etag'} ); $self->assert_num_equals( 0, $writer->{'_one_page'} ); $self->assert_num_equals( 0, $writer->invocation_count( 'start_page' ) ); $self->assert_num_equals( 0, $writer->invocation_count( 'end_page' ) ); $self->assert_num_equals( 1, $writer->invocation_count( 'write_toc' ) ); $self->assert_num_equals( 2, $writer->invocation_count( 'write_section' ) ); $self->assert_num_equals( 2, $writer->invocation_count( 'write_schema' ) ); $self->assert_num_equals( 1, $writer->invocation_count( 'copy_html_files' ) ); $writer->write_report( $self->{'report'}, $output_dir, 'one_page' => 1, 'xhtml' => 0 ); $self->assert_num_equals( 1, $writer->invocation_count( 'start_page' ) ); $self->assert_num_equals( 1, $writer->invocation_count( 'end_page' ) ); $self->assert_str_equals( '>', $writer->{'_etag'} ); $self->assert_num_equals( 1, $writer->{'_one_page'} ); return; } sub create_test_schema { my $self = $_[0]; my $test_schema = new Lire::DlfSchema( 'superservice' => 'test', 'timestamp' => 'time' ); $test_schema->title( '' ); $test_schema->description( 'A description.' ); $test_schema->add_field( new Lire::Field( 'name' => 'time', 'type' => 'timestamp', 'label' => '

    <A title>

    <Time>
    The time field.
    Field 1
    The first field.
    SCHEMA $$buf = ''; $self->{'writer'}{'_one_page'} = 0; $self->{'writer'}->write_schema( 'test'); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'start_page' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'end_page' ) ); $self->assert_str_equals( 'test.html', $self->{'writer'}{'_prev'} ); $self->assert_str_equals( <
    <Time>
    The time field.
    Field 1
    The first field.
    SCHEMA } sub test_write_section { my $self = $_[0]; $self->set_up_report(); my $section = new Lire::Report::Section( 'Empty section' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}{'_one_page'} = 1; $self->{'writer'}->set_result( 'start_page', '' ); $self->{'writer'}->set_result( 'end_page', '' ); $self->{'writer'}->set_result( 'write_subreport', '' ); $self->{'writer'}->write_section( $section, 1 ); $self->assert_num_equals( 0, $self->{'writer'}->invocation_count( 'start_page' ) ); $self->assert_num_equals( 0, $self->{'writer'}->invocation_count( 'end_page' ) ); $self->assert_str_equals( <

    Empty section

    No subreports were generated for this section.

    SECTION $$buf = ''; $self->{'writer'}{'_one_page'} = 0; $section = ($self->{'report'}->sections())[1]; $section->description( 'Section 2 description.' ); $self->{'writer'}->write_section( $section, 2 ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'start_page' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'end_page' ) ); $self->assert_num_equals( 2, $self->{'writer'}->invocation_count( 'write_subreport' ) ); $self->assert_str_equals( 'section-2.html', $self->{'writer'}->{'_prev'} ); $self->assert_str_equals( <

    Section 2

    Section 2 description.
    SECTION } sub test_write_subreport { my $self = $_[0]; $self->set_up_chart_configs(); my $subreport = new Lire::Report::Subreport( 'test', 'top-files' ); $subreport->id( 'top-files' ); $subreport->title( '' ); $subreport->description( 'Subreport description.' ); $subreport->add_chart_config( $self->{'chart1'} ); $subreport->add_chart_config( $self->{'chart2'} ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->set_result( 'write_chart', '' ); $self->{'writer'}->set_result( 'write_table_header', '' ); $self->{'writer'}->set_result( 'write_table_entries', '' ); $self->{'writer'}->set_result( 'write_table_footer', '' ); $self->{'writer'}->write_subreport( $subreport ); $self->assert_num_equals( 2, $self->{'writer'}->invocation_count( 'write_chart' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_table_header' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_table_entries' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'write_table_footer' ) ); $self->assert_str_equals( <

    <Top Files>

    Subreport description.
    SUBREPORT } sub test_write_subreport_missing { my $self = $_[0]; my $sub = new_missing Lire::Report::Subreport( 'test', 'test1', '' ); $sub->id( 'test1' ); $sub->title( '' ); $sub->description( 'Description.' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_subreport( $sub ); $self->assert_str_equals( <

    <My subreport>

    Description.
    This report is missing: <No good reason>
    EOF } sub test_write_toc_one_page { my $self = $_[0]; $self->set_up_report(); $self->{'writer'}{'_report'} = $self->{'report'}; $self->{'writer'}{'_one_page'} = 1; $self->{'writer'}->set_result( 'start_page', '' ); $self->{'writer'}->set_result( 'end_page', '' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_toc(); $self->assert_num_equals( 0, $self->{'writer'}->invocation_count( 'start_page' ) ); $self->assert_num_equals( 0, $self->{'writer'}->invocation_count( 'end_page' ) ); $self->assert_null( $self->{'writer'}{'_toc'}, '_toc != undef' ); $self->assert_null( $self->{'writer'}{'_prev'}, '_next != undef' ); $self->assert_null( $self->{'writer'}{'_next'}, '_next != undef' ); $self->assert_str_equals( <

    Table Of Contents

    1. Simple Schema Definition for Test
    2. Simple Extended Schema for Tests
    TOC } sub test_write_toc { my $self = $_[0]; $self->set_up_report(); $self->{'writer'}{'_report'} = $self->{'report'}; $self->{'writer'}{'_one_page'} = 0; $self->{'writer'}->set_result( 'start_page', '' ); $self->{'writer'}->set_result( 'end_page', '' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_toc(); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'start_page' ) ); $self->assert_num_equals( 1, $self->{'writer'}->invocation_count( 'end_page' ) ); $self->assert_str_equals( 'index.html', $self->{'writer'}{'_toc'} ); $self->assert_str_equals('index.html', $self->{'writer'}{'_prev'} ); $self->assert_str_equals('section-1.html', $self->{'writer'}{'_next'} ); $self->assert_str_equals( <
    1. Simple Schema Definition for Test
    2. Simple Extended Schema for Tests
    TOC } sub test_write_chart { my $self = $_[0]; $self->set_up_chart_configs(); my $subreport = new Lire::Report::Subreport( 'test', 'test1' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_chart( $subreport, $self->{'chart1'} ); $self->assert_str_equals( < <A chart> EOF $self->assert_deep_equals( [ $self->{'mock_chart'}, $self->{'chart1'}, $subreport, 'outputdir', $self->{'tmpdir'}, 'format', 'png' ], $self->{'mock_chart'}->get_invocation( 'write_chart' ) ); $self->{'mock_chart'}->set_result( 'write_chart', sub { die "An error occured\n" } ); $$buf = ''; $self->{'writer'}->write_chart( $subreport, $self->{'chart1'} ); $self->assert_str_equals( < An error occured while generating the chart: An error occured EOF $self->{'mock_chart'}->set_result( 'write_chart', sub { return undef } ); $$buf = ''; $self->{'writer'}->write_chart( $subreport, $self->{'chart1'} ); $self->assert_str_equals( '', $$buf ); } sub test_start_page { my $self = $_[0]; $self->{'writer'}{'_xhtml'} = 1; $self->{'writer'}{'_etag'} = ' />'; $self->{'writer'}{'_fh'} = undef; $self->{'writer'}{'_report'} = new Lire::Report(); $self->{'writer'}->set_result( 'write_navbar', sub { print {$_[0]{'_fh'}} "[write_navbar]\n" } ); $self->{'writer'}->set_result( 'write_report_infos', sub { print {$_[0]{'_fh'}} "[write_report_infos]\n" } ); $self->{'writer'}->set_result( 'write_logo', sub { print {$_[0]{'_fh'}} "[write_logo]\n" } ); $self->{'writer'}->set_result( 'write_links', sub { print {$_[0]{'_fh'}} "[write_links]\n" } ); $self->{'writer'}->start_page( 'index.html', '' ); $self->assert_not_null( $self->{'writer'}{'_fh'}, 'missing _fh attr' ); $self->assert( -f "$self->{'tmpdir'}/index.html" ); $self->{'writer'}{'_fh'}->close(); $self->assert_str_equals( <{'tmpdir'}/index.html" ) ); Lire Report : <A report> [write_links]
    [write_logo] [write_navbar]

    <A report>

    [write_report_infos]
    EOD $self->{'writer'}{'_report'}->title( 'My title' ); $self->{'writer'}{'_xhtml'} = 0; $self->{'writer'}{'_etag'} = '>'; $self->{'writer'}{'_fh'} = undef; $self->{'writer'}->start_page( 'page2.html' ); $self->assert_not_null( $self->{'writer'}{'_fh'}, 'missing _fh attr' ); $self->assert( -f "$self->{'tmpdir'}/page2.html" ); $self->{'writer'}{'_fh'}->close(); $self->assert_str_equals( <{'tmpdir'}/page2.html" ) ); My title [write_links]
    [write_logo] [write_navbar]

    My title

    [write_report_infos]
    EOD } sub test_end_page { my $self = $_[0]; my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->end_page(); $self->assert_null( $self->{'writer'}{'_fh'}, '_fh != undef' ); $self->assert_str_equals( " \n\n", $$buf ); return; } sub test_html_value { my $self = $_[0]; my $writer = $self->{'writer'}; my $nolink_string = ''; my $http_string = 'http://www.logreport.org/'; my $email_string = 'Logreport Wawa Team '; $self->assert_str_equals( '<ordinary string>', $writer->html_value( $nolink_string ) ); $self->assert_str_equals( '
    http://www.logreport.org/', $writer->html_value( $http_string ) ); $self->assert_str_equals( 'Logreport Wawa Team <logrep#r$_wawa-t34m@logreport.org>', $writer->html_value( $email_string ) ); $self->assert_str_equals( 'htt...org/', $writer->html_value( $http_string, 10 ) ); $self->assert_str_equals( 'long...text', $writer->html_value( 'long useless text', 11 ) ); return; } sub test_write_table_header { my $self = $_[0]; $self->set_up_subreport(); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}{'_one_page'} = 0; $self->{'writer'}->write_table_header( $self->{'subreport'} ); $self->assert_str_equals( < <User> Downloads Size <File> EOF return; } sub test_write_table_footer { my $self = $_[0]; $self->set_up_subreport(); $self->{'subreport'}->nrecords( 100 ); $self->{'subreport'}->set_summary_value( 'count', 'content' => '356' ); $self->{'subreport'}->set_summary_value( 'size', 'value' => 1024 * 1024, 'content' => '1 &' ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_table_footer( $self->{'subreport'} ); $self->assert_str_equals( <<'EOF', $$buf ); Total for 100 records 356 1 & EOF } sub test_write_table_entries { my $self = $_[0]; $self->set_up_subreport(); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_table_entries( $self->{'subreport'} ); $self->assert_str_equals( < There is no entries in this table. EOF $self->set_up_subreport_data(); $$buf = ''; $self->{'writer'}->write_table_entries( $self->{'subreport'} ); $self->assert_str_equals( < flacoste 9 53 page1.html 5 50 page2.html 4 3 <wsourdeau> 5 10 page3.html 3 6 page2.html 1 2 page4.html 1 2 EOF } sub test_write_navbar { my $self = $_[0]; my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}{'_one_page'} = 1; $self->{'writer'}->write_navbar(); $self->assert_str_equals( '', $$buf ); $self->{'writer'}{'_one_page'} = 0; $self->{'writer'}{'_next'} = 'section-1.html'; $self->{'writer'}->write_navbar(); $self->assert_str_equals( < Next EOD $$buf = ''; $self->{'writer'}{'_toc'} = 'index.html'; $self->{'writer'}{'_prev'} = 'section-1.html'; $self->{'writer'}{'_next'} = undef; $self->{'writer'}->write_navbar(); $self->assert_str_equals( < Table Of Contents Previous EOD return; } sub test_write_report_infos { my $self = $_[0]; my $report = $self->{'writer'}{'_report'} = new Lire::Report(); $report->date( timelocal( 13, 17, 23, 28, 03, 2004 ) ); $report->timespan_start( timelocal( 14, 15, 18, 28, 03, 2004 ) ); $report->timespan_end( timelocal( 59, 19, 18, 28, 03, 2004 ) ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_report_infos(); $self->assert_str_equals( <<_EOD, $$buf );
    Report generated on: 2004-04-28 23:17:13 UTC
    Reporting on period: 2004-04-28 18:15:14 UTC - 2004-04-28 18:19:59 UTC
    _EOD $$buf = ''; $report->timespan_start( undef ); $self->{'writer'}->write_report_infos(); $self->assert_str_equals( <<_EOD, $$buf );
    Report generated on: 2004-04-28 23:17:13 UTC
    Reporting on period: Unknown Period
    _EOD return; } sub test_write_links { my $self = $_[0]; my $report = $self->{'writer'}{'_report'} = new Lire::Report(); $report->add_section( new Lire::Report::Section( 'Section 1' ) ); $report->add_section( new Lire::Report::Section( 'Section 2' ) ); $report->add_section( new Lire::Report::Section( 'Section 3' ) ); my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}{'_one_page'} = 1; $self->{'cfg'}{'lr_html_css'} = '/usr/share/lire/html/lire-html.css'; $self->{'writer'}->write_links(); $self->assert_str_equals( <<_EOD, $$buf ); _EOD $$buf = ''; $self->{'writer'}{'_one_page'} = 0; $self->{'writer'}{'_toc'} = 'index.html'; $self->{'writer'}{'_next'} = 'section-2.html'; $self->{'writer'}{'_prev'} = 'index.html'; $self->{'cfg'}{'lr_html_css'} = 'http://www.logreport.org/lire.css'; $self->{'writer'}->write_links(); $self->assert_str_equals( <<_EOD, $$buf ); _EOD } sub test_write_logo { my $self = $_[0]; $self->{'cfg'}{'lr_logo'} = undef; my $buf = $self->{'writer'}{'_fh'}->sref(); $self->{'writer'}->write_logo(); $self->assert_str_equals( '', $$buf ); $self->{'cfg'}{'lr_logo'} = '/usr/share/lire/html/lire.png'; $self->{'cfg'}{'lr_logo_url'} = 'http://www.logreport.org/'; $self->{'writer'}->write_logo(); $self->assert_str_equals( <