First commit

This commit is contained in:
Nathan
2026-09-18 20:29:17 -06:00
commit 3b09abe571
2840 changed files with 467153 additions and 0 deletions
@@ -0,0 +1,336 @@
#!/usr/bin/perl
use warnings;
use strict;
use Getopt::Long;
use DBI;
use File::Basename;
use Time::Local;
use List::Util qw/shuffle min/;
my %opt;
GetOptions(
\%opt,
qw/dbname=s dbuser=s dbpass=s prefix=s
total=i start_date=s end_date=s
help/
);
if (defined($opt{help}))
{
print <<FIN;
Fill the user comments table of Piwigo.
Usage: pwg_fill_comments.pl --dbname=<database_name>
--dbuser=<username>
--dbpass=<password>
--tagfile=<tags filename>
[--prefix=<tables prefix>]
[--help]
--dbname, --dbuser and --dbpass are connexion parameters.
--tagfile
--prefix : determines the prefix for your table names.
--help : show this help
FIN
exit(0);
}
my $usage = "\n\n".basename($0)." --help for help\n\n";
foreach my $option (qw/dbname dbuser dbpass start_date end_date/) {
if (not exists $opt{$option}) {
die 'Error: '.$option.' is a mandatory option', $usage;
}
}
$opt{prefix} = 'piwigo_' if (not defined $opt{prefix});
my $dbh = DBI->connect(
'DBI:mysql:'.$opt{dbname},
$opt{dbuser},
$opt{dbpass}
);
my $query;
my $sth;
# retrieve all available users
$query = '
SELECT id
FROM '.$opt{prefix}.'users
';
my @user_ids = keys %{ $dbh->selectall_hashref($query, 'id') };
# set a list of IP addresses for each users
my %user_IPs = ();
foreach my $user_id (@user_ids) {
for (1 .. 1 + int rand 5) {
push(
@{ $user_IPs{$user_id} },
join(
'.',
map {1 + int rand 255} 1..4
)
);
}
}
# use Data::Dumper; print Dumper(\%user_IPs); exit();
# start and end dates
my ($year,$month,$day,$hour,$min,$sec)
= ($opt{start_date} =~ m/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/);
my $start_unixtime = timelocal(0,0,0,$day,$month-1,$year);
($year,$month,$day,$hour,$min,$sec)
= ($opt{end_date} =~ m/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/);
my $end_unixtime = timelocal(0,0,0,$day,$month-1,$year);
# "tags from image" and "images from tag"
$query = '
SELECT image_id, tag_id
FROM '.$opt{prefix}.'image_tag
';
my %image_tags = ();
my %tag_images = ();
my %related_tag_of = ();
my @tags = ();
$sth = $dbh->prepare($query);
$sth->execute();
while (my $row = $sth->fetchrow_hashref()) {
push(
@{$image_tags{$row->{image_id}}},
$row->{tag_id}
);
push(
@{$tag_images{$row->{tag_id}}},
$row->{image_id}
);
push (
@tags,
$row->{tag_id}
);
}
# foreach my $tag_id (keys %tag_images) {
# printf(
# "tag %5u: %5u images\n",
# $tag_id,
# scalar @{$tag_images{$tag_id}}
# );
# }
# exit();
# use Data::Dumper; print Dumper(\%tag_images); exit();
# categories from image_id
$query = '
SELECT image_id, category_id
FROM '.$opt{prefix}.'image_category
';
my %image_categories = ();
my %category_images =();
my %categories = ();
$sth = $dbh->prepare($query);
$sth->execute();
while (my $row = $sth->fetchrow_hashref()) {
push(
@{$image_categories{$row->{image_id}}},
$row->{category_id}
);
push(
@{$category_images{$row->{category_id}}},
$row->{image_id}
);
$categories{ $row->{category_id} }++;
}
my @images = keys %image_categories;
my @categories = keys %categories;
# use Data::Dumper;
# print Dumper(\%image_categories);
my @sections = (
'categories',
# 'tags',
# 'search',
# 'list',
# 'favorites',
# 'most_visited',
# 'best_rated',
# 'recent_pics',
# 'recent_cats',
);
my @inserts = ();
USER : foreach my $user_id (@user_ids) {
print 'user_id: ', $user_id, "\n";
my $current_unixtime = $start_unixtime;
my @IPs = @{ $user_IPs{$user_id} };
VISIT : foreach my $visit_num (1..100_000) {
print 'visit: ', $visit_num, "\n";
my @temp_inserts = ();
my $IP = (@IPs)[int rand @IPs];
my $current_page = 0;
my $visit_size = 10 + int rand 90;
$current_unixtime+= 86_400 + int rand(86_400 * 30);
my $section = $sections[int rand scalar @sections];
# print 'section: ', $section, "\n";
push(
@temp_inserts,
{
section => $section,
}
);
if ($section eq 'categories') {
CATEGORY : foreach my $category_id (
(shuffle @categories)[1..int rand scalar @categories]
) {
# print 'category: ', $category_id, "\n";
push(
@temp_inserts,
{
category_id => $category_id,
}
);
my @images = @{$category_images{$category_id}};
IMAGE : foreach my $image_id (
(shuffle @images)[1..min(10, scalar @images)]
) {
push(
@temp_inserts,
{
category_id => $category_id,
image_id => $image_id,
}
);
}
}
}
if ($section eq 'tags') {
# TODO
}
# transfert @temp_inserts to @inserts
print 'temp_insert size: ', scalar @temp_inserts, "\n";
foreach my $temp_insert (@temp_inserts) {
$current_unixtime+= 5 + int rand 25;
next VISIT if ++$current_page == $visit_size;
last VISIT if $current_unixtime >= $end_unixtime;
my $date = unixtime_to_mysqldate($current_unixtime);
my $time = unixtime_to_mysqltime($current_unixtime);
my ($year, $month, $day) = split '-', $date;
my ($hour) = split ':', $time;
$temp_insert->{date} = $date;
$temp_insert->{time} = $time;
$temp_insert->{year} = $year;
$temp_insert->{month} = $month;
$temp_insert->{day} = $day;
$temp_insert->{hour} = $hour;
$temp_insert->{IP} = $IP;
$temp_insert->{section} = $section;
$temp_insert->{user_id} = $user_id;
push(@inserts, $temp_insert);
}
}
}
@inserts = sort {
$a->{date} cmp $b->{date}
or $a->{time} cmp $b->{time}
} @inserts;
if (scalar @inserts) {
my @columns =
qw/
date time year month day hour
user_id IP
section category_id image_id
/;
my $question_marks_string = '(';
$question_marks_string.= join(
',',
map {'?'} @columns
);
$question_marks_string.= ')';
my $query = '
INSERT INTO '.$opt{prefix}.'history
('.join(', ', @columns).')
VALUES
';
$query.= join(
',',
map {$question_marks_string} (1 .. scalar @inserts)
);
$query.= '
';
# print $query, "\n";
my @values = ();
foreach my $insert (@inserts) {
push(
@values,
map {
$insert->{$_}
} @columns
);
}
$sth = $dbh->prepare($query);
$sth->execute(@values)
or die 'cannot execute insert query';
}
sub unixtime_to_mysqldate {
my ($unixtime) = @_;
($sec,$min,$hour,$day,$month,$year) = localtime($unixtime);
return sprintf(
'%d-%02d-%02d',
$year+1900,
$month+1,
$day,
);
}
sub unixtime_to_mysqltime {
my ($unixtime) = @_;
($sec,$min,$hour,$day,$month,$year) = localtime($unixtime);
return sprintf(
'%d:%d:%d',
$hour,
$min,
$sec
);
}
@@ -0,0 +1,55 @@
<?php
// A) requirements
//
// curl -s http://getcomposer.org/installer | php
// php composer.phar require knplabs/github-api php-http/guzzle6-adapter
//
// B) usage
//
// php gh.php --milestone=2.8.4 --html
$opt = getopt('', array('milestone:', 'html'));
$mandatory_fields = array('milestone');
foreach ($mandatory_fields as $field)
{
if (!isset($opt[$field]))
{
die('missing --'.$field."\n");
}
}
// This file is generated by Composer
require_once 'vendor/autoload.php';
$client = new \Github\Client();
$milestones = $client->api('issue')->milestones()->all('Piwigo', 'Piwigo');
$milestone_number = null;
foreach ($milestones as $milestone)
{
if ($milestone['title'] == $opt['milestone'])
{
$milestone_number = $milestone['number'];
}
}
if (is_null($milestone_number))
{
die('milestone '.$opt['milestone'].' not found');
}
$issues = $client->api('issue')->all('Piwigo', 'Piwigo', array('milestone' => $milestone_number, 'state' => 'closed'));
foreach ($issues as $issue)
{
if (isset($opt['html']))
{
echo '<li><a href="'.$issue['html_url'].'">#'.$issue['number'].'</a>: '.$issue['title'].'</li>'."\n";
}
else
{
echo '#'.$issue['number'].' '.$issue['title']."\n";
}
}
@@ -0,0 +1,15 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
// Recursive call
$url = '../';
header( 'Request-URI: '.$url );
header( 'Content-Location: '.$url );
header( 'Location: '.$url );
exit();
?>
@@ -0,0 +1,653 @@
<?php
$validated_keys = array(
'af_ZA' => array(
'IP: %s',
'IP',
'IPTC Metadata',
'Albums',
'Album',
'%d Kb',
'in %d sub-album',
'in %d sub-albums',
'Admin: %s',
'Album: %s',
'letters',
'EXIF Metadata',
),
'ar_SA' => array(
'IP: %s',
'IP',
'the wiki',
'localhost, sql.multimania.com, toto.freesurf.fr',
),
'bg_BG' => array(
'N/A',
'IP: %s',
),
'cs_CZ' => array(
'Album',
'IP: %s',
'Album: %s',
'IP',
'EXIF Metadata',
'IPTC Metadata',
),
'da_DK' => array(
'%d Kb',
'%d hit',
'%d hits',
'Connection settings',
'Login',
'Display',
'Filter',
'Links',
'N/A',
'Password',
'Quick connect',
'RSS feed',
'Reset',
'Tag',
'Tags',
'Webmaster',
'Administration',
'caddie',
'download',
'Logout',
'Powered by',
'Auto login',
'slideshow',
'SQL queries in',
'Thumbnails',
'Menu',
'IP: %s',
'Browser: %s',
'Email: %s',
'Admin: %s',
'Rank',
'cloud',
'Pause of slideshow',
'Database type',
'Installation',
'Webmaster login',
'localhost, sql.multimania.com, toto.freesurf.fr',
'Webmaster password',
'%d tag',
'%d tags',
'Caddie',
'Database',
'Elements',
'Form',
'Gallery URL',
'Path',
'Permalink',
'Permalinks',
'Plugins',
'Position',
'Rating',
'Representant',
'Site manager',
'Status',
'Version',
'Main',
'File',
'High definition',
'email',
'Send',
'Remote',
'Piwigo administration',
'GD version',
'[Simulation]',
'Upload',
'user_status_admin',
'user_status_webmaster',
'IP',
'Element',
'Element type',
'Hoverbox display',
'Level 8',
'Plugins up to date',
'Support',
'Piwigo Administration',
'Piwigo version',
'Original templates',
'Downloads',
'Download',
'Hit',
'Resize',
'Miscellaneous',
'Virtual Links',
'SQL queries',
'Edit',
'%d rates',
'Rating score',
'Password Reset',
'Invalid key',
'EXIF Metadata',
'IPTC Metadata',
),
'de_DE' => array(
'%d Kb',
'Filter',
'Links',
'Tag',
'Tags',
'Webmaster',
'Administration',
'Thumbnails',
'IP: %s',
'Browser: %s',
'Name',
'Permalink',
'Permalinks',
'Plugins',
'Position',
'Status',
'Version',
'High definition',
'Parameter',
'private',
'Thumbnail',
'Simulation',
'Upload',
'user_status_admin',
'user_status_webmaster',
'IP',
'Privacy level',
'Demo',
'Support',
'Bugs',
'Downloads',
'Installation',
'localhost, sql.multimania.com, toto.freesurf.fr',
'Upgrade',
'Download,',
'Piwigo Uploader',
'[Simulation]',
'Album',
'Album: %s',
'Remote',
),
'el_GR' => array(
'%d Kb',
'Email: %s',
'IP: %s',
'Powered by',
),
'es_AR' => array(
'%d Kb',
'Webmaster',
'IP: %s',
'No',
),
'es_ES' => array(
'Tag',
'Tags',
'IP: %s',
'Email: %s',
'No',
'%d tag',
'%d tags',
'Plugins',
'is_high_disabled',
'nbm_content_goto_2',
'nbm_content_hello_2',
'site_local',
'update_simulation_title',
'IP',
'Level 8',
'DEMO',
'BUGS',
'step1_host_info',
'Albums',
'General',
'Local',
'Demo',
'Bugs',
'localhost, sql.multimania.com, toto.freesurf.fr',
'Piwigo Uploader',
),
'fr_FR' => array(
'Dimensions',
'Identification',
'Notification',
'Tag',
'Tags',
'admin',
'identification',
'redirect_msg',
'search_date_from',
'title_menu',
'IP: %s',
'Email: %s',
'%d element',
'%d elements',
'%d association',
'%d associations',
'%d tag',
'%d tags',
'Actions',
'Description',
'Informations',
'Maintenance',
'Options',
'Plugins',
'Position',
'Validation',
'Version',
'config',
'Date',
'instructions',
'is_high_disabled',
'nbm_content_goto_2',
'nbm_content_hello_2',
'nbm_item_notification',
'nbm_send_options',
'permissions',
'public',
'site_local',
'update_simulation_title',
'IP',
'image',
'section',
'tags',
'high',
'c13y_Correction',
'Level 1',
'Level 8',
'FORUM',
'EXTENSIONS',
'WIKI / DOC',
'Installation',
'step1_host_info',
'Administration',
'Redirection...',
'Menu',
'%d photo',
'%d photos',
'Configuration',
'Instructions',
'Permissions',
'Local',
'[Simulation]',
'Section',
'Correction',
'Support',
'Extensions',
'Documentation',
'Photos',
'photo',
'pixels',
'Piwigo Uploader',
'localhost, sql.multimania.com, toto.freesurf.fr',
'email',
'Albums',
'Album',
'Menu Management',
'Action',
'Simulation',
),
'he_IL' => array(
'localhost, sql.multimania.com, toto.freesurf.fr',
),
'hr_HR' => array(
'%d Kb',
'Filter',
'Tag',
'Webmaster',
'IP: %s',
'%d tag',
'user_status_webmaster',
'IP',
'localhost, sql.multimania.com, toto.freesurf.fr',
),
'hu_HU' => array(
'Album',
'Album: %s',
),
'is_IS' => array(
'%d Kb',
'N/A',
'IP: %s',
'Admin: %s',
),
'it_IT' => array(
'Album',
'Album: %s',
'Browser: %s',
'Database',
'Directory',
'Download',
'Downloads',
'email',
'Email',
'Email: %s',
'File',
'Home',
'high',
'Host',
'IP',
'IP: %s',
'Links',
'Logout',
'Menu',
'N/A',
'No',
'Password',
'Permalink',
'Permalinks',
'pixels',
'Piwigo Uploader',
'Plugin',
'Plugins',
'Tag',
'Tags',
'%d tag',
'%d tags',
'Tools',
'user_status_webmaster',
'Webmaster',
'in %d sub-album',
),
'ja_JP' => array(
'About',
'Since',
'Powered by',
'IP: %s',
'IP',
'Sent by',
'%d Kb',
'',
),
'lv_LV' => array(
'%d Kb',
'N/A',
'IP: %s',
'IP',
'localhost, sql.multimania.com, toto.freesurf.fr',
),
'nl_NL' => array(
'%d Kb',
'Filter',
'Help',
'Links',
'RSS feed',
'Reset',
'Tag',
'Tags',
'Week %d',
'download',
'Powered by',
'Auto login',
'Contact',
'SQL queries in',
'Menu',
'IP: %s',
'Browser: %s',
'Email: %s',
'Piwigo Help',
'%d tag',
'%d tags',
'Batch management',
'Database',
'Permalink',
'Permalinks',
'Plugins',
'Representant',
'Site manager',
'Status',
'email',
'Parameter',
'Parameters',
'Remote site',
'test',
'Remote',
'unit mode',
'Upload',
'IP',
'Level 8',
'Demo',
'Hits',
'Downloads',
'localhost, sql.multimania.com, toto.freesurf.fr',
'Upgrade',
'SQL queries',
'letters',
'This author removed the comment with id %d',
'Database type',
'Sorry!',
'Hope to see you back soon.',
'Hit',
'pixels',
'Download',
'Piwigo Uploader',
'Download,',
'Compact',
'Updates',
'ERROR',
'Piwigo Update',
'Dump Database',
'Start Upload',
),
'no_NO' => array(
'IP: %s',
'Browser: %s',
'Email: %s',
'Admin: %s',
'Pause of slideshow',
'Album',
'Filter',
'N/A',
'Webmaster',
'%d Kb',
'representative',
'slideshow',
'Album: %s',
'Album results for',
'%d tag',
'Database',
'Permalink',
'Representant',
'Representative',
'Status',
'Main',
'email',
'Parameter',
'Send',
'test',
'status',
'user_status_admin',
'user_status_webmaster',
'IP',
'Element',
'Tags',
'Element type',
'Database type',
'Host',
'localhost, sql.multimania.com, toto.freesurf.fr',
),
'pl_PL' => array(
'%d Kb',
'RSS feed',
'Webmaster',
'IP: %s',
'Tag',
'Powered by',
'Email: %s',
'Admin: %s',
'%d tag',
'Status',
'test',
'status',
'user_status_admin',
'user_status_webmaster',
'localhost, sql.multimania.com, toto.freesurf.fr',
'IP',
'Menu',
'Album',
),
'pt_BR' => array(
'localhost, sql.multimania.com, toto.freesurf.fr',
),
'pt_PT' => array(
'%d Kb',
'Links',
'Webmaster',
'Powered by',
'IP: %s',
'Email: %s',
'localhost, sql.multimania.com, toto.freesurf.fr',
'Permalinks',
'Plugins',
'Local',
'user_status_webmaster',
'IP',
'Downloads',
'Download',
'Download,',
'EXIF Metadata',
'IPTC Metadata',
'Original',
'Zoom',
'',
),
'ro_RO' => array(
'%d Kb',
'N/A',
'RSS feed',
'Webmaster',
'Calendar',
'Contact',
),
'ru_RU' => array(
'IP',
'IP: %s',
'localhost, sql.multimania.com, toto.freesurf.fr',
'',
),
'sl_SL' => array(
'%d Kb',
'Filter',
'N/A',
'caddie',
'IP: %s',
'show tag cloud',
'cloud',
),
'sk_SK' => array(
'%d Kb',
'Album',
'Filter',
'Webmaster',
'IP: %s',
'Album: %s',
'test',
'user_status_webmaster',
'IP',
'EXIF Metadata',
'IPTC Metadata',
),
'sr_RS' => array(
'%d Kb',
'Filter',
'Webmaster',
'IP: %s',
'user_status_admin',
'user_status_webmaster',
'IP',
'Element',
'Host',
'localhost, sql.multimania.com, toto.freesurf.fr',
),
'sv_SE' => array(
'%d association',
'Plugins',
'Position',
'Representant',
'Status',
'Version',
'High definition',
'test',
'status',
'Piwigo administration',
'GD version',
'user_status_webmaster',
'IP',
'Element',
'Piwigo Administration',
'Piwigo version',
'IP: %s',
'Admin: %s',
'Filter',
'Administration',
'%d Kb',
'Installation',
'localhost, sql.multimania.com, toto.freesurf.fr',
'Album: %s',
'Album',
'Informations',
'EXIF Metadata',
'IPTC Metadata',
'Original',
'Desktop',
),
'tr_TR' => array(
'%d hit',
'N/A',
'Webmaster',
'IP: %s',
'Host',
'localhost, sql.multimania.com, toto.freesurf.fr',
),
'vi_VN' => array(
'%d Kb',
'Caddie',
'Form',
'Plugins',
'user_status_webmaster',
'Templates',
'pixels',
'localhost, sql.multimania.com, toto.freesurf.fr',
'Desktop',
),
'zh_CN' => array(
'IP',
'localhost, sql.multimania.com, toto.freesurf.fr',
'%d Kb',
),
'zh_TW' => array(
'IP',
'localhost, sql.multimania.com, toto.freesurf.fr',
),
);
?>
@@ -0,0 +1,118 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
$filename = 'sample.jpg';
echo 'Informations are read from '.$filename.'<br><br><br>';
/**
* return a cleaned IPTC value
*
* @param string value
* @return string
*/
function clean_iptc_value($value)
{
// strip leading zeros (weird Kodak Scanner software)
while ( isset($value[0]) and $value[0] == chr(0))
{
$value = substr($value, 1);
}
// remove binary nulls
$value = str_replace(chr(0x00), ' ', $value);
return $value;
}
$iptc_result = array();
$imginfo = array();
getimagesize($filename, $imginfo);
if (isset($imginfo['APP13']))
{
$iptc = iptcparse($imginfo['APP13']);
if (is_array($iptc))
{
foreach (array_keys($iptc) as $iptc_key)
{
if (isset($iptc[$iptc_key][0]))
{
if ($iptc_key == '2#025')
{
$value = implode(
',',
array_map(
'clean_iptc_value',
$iptc[$iptc_key]
)
);
}
else
{
$value = clean_iptc_value($iptc[$iptc_key][0]);
}
$iptc_result[$iptc_key] = $value;
}
}
}
echo 'IPTC Fields in '.$filename.'<br>';
$keys = array_keys($iptc_result);
sort($keys);
foreach ($keys as $key)
{
echo '<br>'.$key.' = '.$iptc_result[$key];
}
}
else
{
echo 'no IPTC information';
}
echo '<br><br><br>';
echo 'EXIF Fields in '.$filename.'<br>';
$exif = exif_read_data($filename);
echo '<pre>';
print_r($exif);
echo '</pre>';
#
# Display XMP metadata using ImageMagick PHP extension
#
print "<h3>XMP data in '{$filename}'</h3><br />" ;
print ' (Requires Imagemagick PHP extension)<br />' ;
print '<pre>' ;
if( extension_loaded('imagick') && class_exists("Imagick") ){ //Check ImageMagick is installed
// create new Imagick object from image
$sampleIM = new imagick($filename) ;
// get the XMP data
$sampleXMP = $sampleIM -> getImageProperties("xmp:*") ;
// If there's data, then loop through the XMP array
if ( count($sampleXMP) ) {
foreach ($sampleXMP as $XMPname => $XMPproperty) {
print "{$XMPname} => {$XMPproperty} <br />\n" ;
}
}else{
print 'No data <br /> ';
}
print '[end of XMP]' ;
}else{
print 'ImageMagick not detected or disabled' ;
}
print '</pre>' ;
?>
@@ -0,0 +1,193 @@
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
our %used_keys = ();
our %registered_keys = ();
my $piwigo_dir = $ARGV[0]; # '/home/pierrick/public_html/piwigo/dev/trunk';
my $type = $ARGV[1]; # common, admin, install, upgrade
find(\&used_keys, $piwigo_dir);
load_registered_keys($type);
# foreach my $key (sort keys %used_keys) {
# # print "{".$key."}", ' is used', "\n";
# if (not defined $registered_keys{$key}) {
# # print "{".$key."}", ' is missing', "\n";
# print '$lang[\''.$key.'\'] = \''.$key.'\';', "\n";
# }
# }
my %ignore_keys = (
'%d new photo' => 1,
'%d new photos' => 1,
'%d category updated' => 1,
'%d categories updated' => 1,
'%d new comment' => 1,
'%d new comments' => 1,
'%d comment to validate' => 1,
'%d comments to validate' => 1,
'%d new user' => 1,
'%d new users' => 1,
'%d waiting element' => 1,
'%d waiting elements' => 1,
'user_status_admin' => '',
'user_status_generic' => '',
'user_status_guest' => '',
'user_status_normal' => '',
'user_status_webmaster' => '',
'Level 0' => '',
'Level 1' => '',
'Level 2' => '',
'Level 4' => '',
'Level 8' => '',
'ACCESS_0' => '',
'ACCESS_1' => '',
'ACCESS_2' => '',
'ACCESS_3' => '',
'ACCESS_4' => '',
'ACCESS_5' => '',
'month' => '',
'day' => '',
'chronology_monthly_calendar' => '',
'chronology_monthly_list' => '',
'chronology_weekly_list' => '',
'public' => '',
'private' => '',
'none' => '',
'other' => '',
'high' => '',
'Waiting page: %s' => '',
'Admin: %s' => '',
'Manage this user comment: %s' => '',
'Main "guest" user does not exist' => '',
'Main "guest" user status is incorrect' => '',
'Main "webmaster" user does not exist' => '',
'Main "webmaster" user status is incorrect' => '',
'Default user does not exist' => '',
'(!) This comment requires validation' => '',
);
foreach my $key (sort keys %registered_keys) {
if (not defined $used_keys{$key} and not defined $ignore_keys{$key}) {
print "{".$key."}", ' is not used anywhere', "\n";
}
}
sub used_keys {
if ($File::Find::name !~ m/(tpl|php)$/) {
return 0;
}
if ($File::Find::name =~ m{/(plugins|language|_data)/}) {
return 0;
}
if ('upgrade' eq $type) {
if ($File::Find::name !~ m{upgrade\.(tpl|php)$}) {
# return 0;
}
}
if ('install' eq $type) {
if ($File::Find::name =~ m{upgrade\.(tpl|php)$}) {
return 0;
}
if ($File::Find::name !~ m{/install(\.tpl|\.php|/)}) {
return 0;
}
}
if ('admin' eq $type) {
if ($File::Find::name =~ m{upgrade\.(tpl|php)$}) {
return 0;
}
if ($File::Find::name =~ m{/install(\.tpl|\.php|/)}) {
return 0;
}
my $is_admin = 0;
if ($File::Find::name =~ m{themes/default/template/mail}) {
$is_admin = 1;
}
if ($File::Find::name =~ m{/admin/}) {
$is_admin = 1;
}
if ($File::Find::name =~ m{/admin\.php$}) {
$is_admin = 1;
}
if (not $is_admin) {
return 0;
}
}
if ('common' eq $type) {
if ($File::Find::name =~ m{upgrade\.(tpl|php)$}) {
return 0;
}
if ($File::Find::name =~ m{/install(\.tpl|\.php|/)}) {
return 0;
}
if ($File::Find::name =~ m{/admin(/|\.php)} or $File::Find::name =~ m{themes/default/template/mail}) {
return 0;
}
}
if (-f) {
my $big_string = '';
open(my $fhi, '<', $File::Find::name);
while (<$fhi>) {
chomp;
s{//.*$}{};
$big_string.= $_;
}
close($fhi);
while ($big_string =~ m/\{(['"])(.+?)\1\|\@translate/g) {
$used_keys{$2}++;
}
while ($big_string =~ m/l10n \s* \( \s* (['"]) (.+?) \1 \s* \)/xg) {
$used_keys{$2}++;
}
while ($big_string =~ m/l10n_args \s* \( \s* (['"]) (.+?) \1 \s* ,/xg) {
$used_keys{$2}++;
}
while ($big_string =~ m/l10n_dec \s* \( \s* (['"]) (.+?) \1 \s* ,\s* (['"]) (.+?) \3 \s* ,/xg) {
$used_keys{$2}++;
$used_keys{$4}++;
}
}
}
sub load_registered_keys {
my ($type) = @_;
my %files_for_type = (
common => [qw/common/],
admin => [qw/common admin/],
install => [qw/common admin install/],
upgrade => [qw/common admin install upgrade/],
);
foreach my $file_code (@{$files_for_type{$type}}) {
my $filepath = $piwigo_dir.'/language/en_UK/'.$file_code.'.lang.php';
open(my $fhi, '<', $filepath);
while (<$fhi>) {
if (m/\$lang\[ \s* (['"]) (.+?) \1 \s* \]/x) {
$registered_keys{$2}++;
}
}
}
}
@@ -0,0 +1,36 @@
#!/usr/bin/perl
use LWP::UserAgent;
my %conf = (
base_url => 'http://localhost/pwggit',
);
my $ua = LWP::UserAgent->new;
$ua->cookie_jar({});
$ua->post(
$conf{base_url}.'/ws.php',
{
method => 'pwg.session.login',
username => 'plg',
password => 'plg',
}
);
my $response = $ua->post(
$conf{base_url}.'/ws.php',
{
method => 'pwg.images.addSimple',
image => ['/Users/plg/Documents/IMG_7779.jpg'],
category => 6,
tags => 'tag1, tag2, another tag',
name => 'A nice title',
comment => 'A longer description',
author => 'Paul Nikanon',
level => 0,
},
'Content_Type' => 'form-data',
);
use Data::Dumper; print Dumper($response->message);
@@ -0,0 +1,434 @@
#!/usr/bin/perl
####
# Usage examples
#
# perl piwigo_remote.pl --action=pwg.images.add --file=erwann_rocher-web.jpg --define categories=9
use strict;
use warnings;
use JSON;
use LWP::UserAgent;
# LWP::Debug::level('+');
use Getopt::Long;
use Encode qw/is_utf8 decode/;
use POSIX qw(ceil floor);
my %opt = ();
GetOptions(
\%opt,
qw/
action=s
file=s
original=s
categories=s
chunk_size=i
base_url=s
username=s
password=s
define=s%
/
);
our $ua = LWP::UserAgent->new;
$ua->agent('Mozilla/piwigo_remote.pl 1.25');
$ua->cookie_jar({});
my %conf;
$conf{response_format} = 'json';
$conf{limit} = 10;
my %conf_default = (
base_url => 'http://localhost/piwigo/2.0',
username => 'plg',
password => 'plg',
chunk_size => 500_000,
);
foreach my $conf_key (keys %conf_default) {
$conf{$conf_key} = defined $opt{$conf_key} ? $opt{$conf_key} : $conf_default{$conf_key}
}
$ua->default_headers->authorization_basic(
$conf{username},
$conf{password}
);
my $result = undef;
my $query = undef;
binmode STDOUT, ":encoding(utf-8)";
# TODO : don't connect at each script call, use the session duration instead.
my $form = {
method => 'pwg.session.login',
username => $conf{username},
password => $conf{password},
};
$result = $ua->post(
$conf{base_url}.'/ws.php?format=json',
$form
);
# print "\n", $ua->cookie_jar->as_string, "\n";
if ($opt{action} eq 'pwg.images.add') {
use Digest::MD5::File qw/file_md5_hex/;
$form = {};
$form->{method} = $opt{action};
my $original = $opt{file};
if (defined $opt{original}) {
$original = $opt{original};
}
my $original_sum = file_md5_hex($original);
$form->{original_sum} = $original_sum;
send_chunks(
filepath => $opt{file},
type => 'file',
original_sum => $original_sum,
);
$form->{file_sum} = file_md5_hex($opt{file});
foreach my $key (keys %{ $opt{define} }) {
$form->{$key} = $opt{define}{$key};
}
my $response = $ua->post(
$conf{base_url}.'/ws.php?format=json',
$form
);
print "-" x 50, "\n";
printf("response code : %u\n", $response->code);
printf("response message : %s\n", $response->message);
print "-" x 50, "\n";
print "\n";
# use Data::Dumper;
# print Dumper($response->content);
# print Dumper(from_json($response->content));
if ($response->is_success) {
print "upload successful\n";
}
else {
print Dumper($response);
warn 'A problem has occured during upload', "\n";
warn $response->decoded_content, "\n";
die $response->status_line;
}
}
if ($opt{action} eq 'pwg.images.addFile') {
use Digest::MD5::File qw/file_md5_hex/;
if (not defined $opt{define}{image_id}) {
die '--define image_id=1234 is missing';
}
# which file type are we going to add/update?
my $type = undef;
foreach my $test_type (qw/thumbnail file high/) {
if (defined $opt{$test_type}) {
$type = $test_type;
last;
}
}
if (not defined $type) {
die 'at least one of file/thumbnail/high parameters must be set';
}
my $type_code = typecode_from_typename($type);
send_chunks(
filepath => $opt{$type},
type => $type_code,
original_sum => file_md5_hex($opt{original}),
);
$form = {};
$form->{method} = $opt{action};
$form->{type} = $type_code;
$form->{sum} = file_md5_hex($opt{$type});
foreach my $key (keys %{ $opt{define} }) {
$form->{$key} = $opt{define}{$key};
}
my $response = $ua->post(
$conf{base_url}.'/ws.php?format=json',
$form
);
print "-" x 50, "\n";
printf("response code : %u\n", $response->code);
printf("response message : %s\n", $response->message);
print "-" x 50, "\n";
print "\n";
# use Data::Dumper;
# print Dumper($response->content);
# print Dumper(from_json($response->content));
if ($response->is_success) {
print "upload successful\n";
}
else {
print Dumper($response);
warn 'A problem has occured during upload', "\n";
warn $response->decoded_content, "\n";
die $response->status_line;
}
}
if ($opt{action} eq 'pwg.tags.list') {
use Text::ASCIITable;
$query = pwg_ws_get_query(
method => 'pwg.tags.getList',
sort_by_counter => 'true',
);
$result = $ua->get($query);
my $tag_result = from_json($result->content);
my $t = Text::ASCIITable->new({ headingText => 'Tags' });
$t->setCols('id','counter','name');
my $tag_number = 1;
foreach my $tag_href (@{ $tag_result->{result}{tags} }) {
$t->addRow(
$tag_href->{id},
$tag_href->{counter},
$tag_href->{name}
);
last if $tag_number++ >= $conf{limit};
}
print $t;
}
if ($opt{action} eq 'pwg.tags.getAdminList') {
$query = pwg_ws_get_query(
method => 'pwg.tags.getAdminList'
);
$result = $ua->get($query);
print Dumper($result);
my $tags = from_json($result->content)->{result}{tags};
foreach my $tag (@{$tags}) {
# print join(',', keys %{$tag}), "\n"; exit();
printf(
'{%u} %s ',
$tag->{id},
$tag->{name}
);
}
print "\n";
}
if ($opt{action} eq 'pwg.categories.add') {
$form = {
method => 'pwg.categories.add',
name => $opt{define}{name},
parent => $opt{define}{parent},
comment => $opt{define}{comment},
};
my $response = $ua->post(
$conf{base_url}.'/ws.php?format=json',
$form
);
use Data::Dumper;
print Dumper(from_json($response->content));
}
if ($opt{action} eq 'pwg.tags.add') {
$form = {
method => 'pwg.tags.add',
name => $opt{define}{name},
};
my $response = $ua->post(
$conf{base_url}.'/ws.php?format=json',
$form
);
use Data::Dumper;
print Dumper(from_json($response->content));
}
if ($opt{action} eq 'pwg.images.exist') {
$form = {
method => $opt{action},
};
foreach my $key (keys %{ $opt{define} }) {
$form->{$key} = $opt{define}{$key};
}
my $response = $ua->post(
$conf{base_url}.'/ws.php?format=json',
$form
);
use Data::Dumper;
print Dumper(from_json($response->content)->{result});
# print Dumper($response);
}
if ($opt{action} eq 'pwg.images.checkFiles') {
use Digest::MD5::File qw/file_md5_hex/;
$form = {};
$form->{method} = $opt{action};
foreach my $type (qw/thumbnail file high/) {
if (defined $opt{$type}) {
$form->{$type.'_sum'} = file_md5_hex($opt{$type});
}
}
foreach my $key (keys %{ $opt{define} }) {
$form->{$key} = $opt{define}{$key};
}
my $response = $ua->post(
$conf{base_url}.'/ws.php?format=json',
$form
);
print "-" x 50, "\n";
printf("response code : %u\n", $response->code);
printf("response message : %s\n", $response->message);
print "-" x 50, "\n";
print "\n";
use Data::Dumper;
print Dumper(from_json($response->content));
}
if ($opt{action} eq 'pwg.images.setInfo' or $opt{action} eq 'pwg.categories.setInfo') {
$form = {
method => $opt{action},
};
foreach my $key (keys %{ $opt{define} }) {
$form->{$key} = $opt{define}{$key};
}
my $response = $ua->post(
$conf{base_url}.'/ws.php?format=json',
$form
);
use Data::Dumper;
# print Dumper(from_json($response->content)->{result});
print Dumper($response);
}
if ($opt{action} eq 'pwg.categories.getList') {
$form = {
method => $opt{action},
};
foreach my $key (keys %{ $opt{define} }) {
$form->{$key} = $opt{define}{$key};
}
my $response = $ua->post(
$conf{base_url}.'/ws.php?format=json',
$form
);
use Data::Dumper;
print Dumper($response->content);
print Dumper(from_json($response->content)->{result});
print Dumper($response);
}
$query = pwg_ws_get_query(
method => 'pwg.session.logout'
);
$ua->get($query);
sub pwg_ws_get_query {
my %params = @_;
my $query = $conf{base_url}.'/ws.php?format='.$conf{response_format};
foreach my $key (keys %params) {
$query .= '&'.$key.'='.$params{$key};
}
return $query;
}
sub send_chunks {
my %params = @_;
use MIME::Base64 qw(encode_base64);
use File::Slurp;
my $content = read_file($params{filepath});
my $content_length = length($content);
my $nb_chunks = ceil($content_length / $conf{chunk_size});
my $chunk_pos = 0;
my $chunk_id = 1;
while ($chunk_pos < $content_length) {
my $chunk = substr(
$content,
$chunk_pos,
$conf{chunk_size}
);
$chunk_pos += $conf{chunk_size};
my $response = $ua->post(
$conf{base_url}.'/ws.php?format=json',
{
method => 'pwg.images.addChunk',
data => encode_base64($chunk),
original_sum => $params{original_sum},
position => $chunk_id,
type => $params{type},
}
);
printf(
'chunk %05u of %05u for %s "%s"'."\n",
$chunk_id,
$nb_chunks,
$params{type},
$params{filepath}
);
if ($response->code != 200) {
printf("response code : %u\n", $response->code);
printf("response message : %s\n", $response->message);
}
$chunk_id++;
}
}
sub typecode_from_typename {
my ($typename) = @_;
my $typecode = $typename;
if ('thumbnail' eq $typename) {
$typecode = 'thumb';
}
return $typecode;
}
@@ -0,0 +1,121 @@
#!/usr/bin/perl
####
# Usage
#
# perl piwigo_upload.pl --url=http://piwigo.org/demo --user=admin --password=secret --file=photo.jpg --album_id=9
use strict;
use warnings;
use JSON;
use LWP::UserAgent;
use Getopt::Long;
use POSIX qw(ceil floor);
use Digest::MD5 qw/md5 md5_hex/;
use File::Slurp;
use File::Basename;
my %opt = ();
GetOptions(
\%opt,
qw/
file=s
album_id=i
category=s
url=s
username=s
password=s
/
);
our %conf = (
chunk_size => 500_000,
);
our $ua = LWP::UserAgent->new;
$ua->agent('Mozilla/piwigo_upload.pl 1.56');
$ua->cookie_jar({});
my $result = undef;
my $form = {
method => 'pwg.session.login',
username => $opt{username},
password => $opt{password},
};
$result = $ua->post(
$opt{url}.'/ws.php?format=json',
$form
);
my $response = $ua->post(
$opt{url}.'/ws.php?format=json',
{
method => 'pwg.session.getStatus',
}
);
my $pwg_token = from_json($response->content)->{result}->{pwg_token};
my $content = read_file($opt{file});
my $content_length = length($content);
my $nb_chunks = ceil($content_length / $conf{chunk_size});
my $chunk_pos = 0;
my $chunk_id = 0;
while ($chunk_pos < $content_length) {
my $chunk = substr(
$content,
$chunk_pos,
$conf{chunk_size}
);
# write the chunk as a temporary local file
my $chunk_path = '/tmp/'.md5_hex($opt{file}).'.chunk';
open(my $ofh, '>'.$chunk_path) or die "problem for writing temporary local chunk";
print {$ofh} $chunk;
close($ofh);
$chunk_pos += $conf{chunk_size};
my $response = $ua->post(
$opt{url}.'/ws.php?format=json',
{
method => 'pwg.images.upload',
chunk => $chunk_id,
chunks => $nb_chunks,
category => $opt{album_id},
pwg_token => $pwg_token,
file => [$chunk_path],
name => basename($opt{file}),
},
'Content_Type' => 'form-data',
);
unlink($chunk_path);
printf(
'chunk %03u of %03u for "%s"'."\n",
$chunk_id+1,
$nb_chunks,
$opt{file}
);
if ($response->code != 200) {
printf("response code : %u\n", $response->code);
printf("response message : %s\n", $response->message);
}
$chunk_id++;
}
$result = $ua->get(
$opt{url}.'/ws.php?format=json',
{
method => 'pwg.session.logout'
}
);
+142
View File
@@ -0,0 +1,142 @@
#!/bin/bash
script_abspath=$(perl -e 'use Cwd "abs_path"; print abs_path(@ARGV[0])' -- "$0")
scriptdir=$(dirname $script_abspath)
# +--------------------------------------------------------------------------+
# | pwg_rel_create.sh |
# +--------------------------------------------------------------------------+
# | author : Pierrick LE GALL <http://le-gall.net/pierrick> |
# | project : Piwigo |
# +--------------------------------------------------------------------------+
if [ $# -lt 1 ]
then
echo
echo 'usage : '$(basename $0)' <version number> [<sha>]'
echo
exit 1
fi
version=$1
sha=$2
name=piwigo-$version
cd /tmp
if [ -e $version ]
then
rm -rf $version
fi
mkdir $version
cd $version
git clone git@github.com:Piwigo/Piwigo.git piwigo
cd piwigo
if [ $# -eq 2 ]
then
git checkout $2
fi
# remove Git metadata
rm -rf /tmp/$version/piwigo/.git
# +--------------------------------------------------------------------------+
# | plugins |
# +--------------------------------------------------------------------------+
cd plugins
for plugin in TakeATour AdminTools LocalFilesEditor LanguageSwitch
do
cd /tmp/$version/piwigo/plugins
plugin_dir=$plugin
if [ $plugin = "LanguageSwitch" ]
then
plugin_dir=language_switch
fi
# clone repo
git clone git@github.com:Piwigo/${plugin}.git $plugin_dir
cd /tmp/$version/piwigo/plugins/$plugin_dir
# change version
perl $scriptdir/replace_version.pl --file=main.inc.php --version=$version
# register metadata in dedicated file
echo https://github.com/Piwigo/${plugin}.git > pem_metadata.txt
git log -n 1 --pretty=format:"%H %ad" --date=iso8601 >> pem_metadata.txt
# remove Git metadata
rm -rf .git
done
# +--------------------------------------------------------------------------+
# | themes |
# +--------------------------------------------------------------------------+
for theme in modus elegant smartpocket
do
cd /tmp/$version/piwigo/themes
git_url=git@github.com:Piwigo/piwigo-${theme}.git
# clone repo
git clone $git_url $theme
# enter theme directory for next actions
cd $theme
# change version
perl $scriptdir/replace_version.pl --file=themeconf.inc.php --version=$version
# register metadata in dedicated file
echo $git_url > pem_metadata.txt
git log -n 1 --pretty=format:"%H %ad" --date=iso8601 >> pem_metadata.txt
# remove Git metadata
rm -rf .git
done
# +--------------------------------------------------------------------------+
# | languages |
# +--------------------------------------------------------------------------+
cd /tmp/$version/piwigo/language
for languagefile in $(ls */common.lang.php)
do
# change version
perl $scriptdir/replace_version.pl --file=$languagefile --version=$version
done
# +--------------------------------------------------------------------------+
# | data directories + zip 1 |
# +--------------------------------------------------------------------------+
# create "data" directories
cd /tmp/$version
mkdir piwigo/upload
mkdir piwigo/_data
touch piwigo/_data/dummy.txt
zip -q -r $name-nochmod.zip piwigo
# +--------------------------------------------------------------------------+
# | permissions + zip 2 |
# +--------------------------------------------------------------------------+
chmod -R g-w piwigo
chmod -R a+w piwigo/local
chmod a+w piwigo/_data
chmod a+w piwigo/upload
chmod a+w piwigo/plugins
chmod a+w piwigo/themes
zip -q -r $name.zip piwigo
echo cd /tmp/$version
@@ -0,0 +1,59 @@
#!/usr/bin/perl
# perl remote_sync.pl --base_url=http://localhost/piwigo/dev/branches/2.0 --username=plg --password=plg
use strict;
use warnings;
use LWP::UserAgent;
use Getopt::Long;
my %opt = ();
GetOptions(
\%opt,
qw/
base_url=s
username=s
password=s
/
);
our $ua = LWP::UserAgent->new;
$ua->agent('Mozilla/remote_sync.pl');
$ua->cookie_jar({});
$ua->default_headers->authorization_basic(
$opt{username},
$opt{password}
);
my $form = {
method => 'pwg.session.login',
username => $opt{username},
password => $opt{password},
};
my $result = $ua->post(
$opt{base_url}.'/ws.php?format=json',
$form
);
# perform the synchronization
$form = {
'sync' => 'files',
'display_info' => 1,
'add_to_caddie' => 1,
'privacy_level' => 0,
'sync_meta' => 1, # remove this parameter, turning to 0 is not enough
'simulate' => 0,
'subcats-included' => 1,
'submit' => 1,
};
$result = $ua->post(
$opt{base_url}.'/admin.php?page=site_update&site=1',
$form
);
use Data::Dumper;
print Dumper($result);
@@ -0,0 +1,39 @@
#!/usr/bin/perl
####
# Usage
#
# perl replace_version.pl --file=/path/to/file.php --version=2.8.0
use strict;
use warnings;
use Getopt::Long;
use File::Basename;
my %opt = ();
GetOptions(
\%opt,
qw/
file=s
version=s
/
);
if (not -e $opt{file}) {
die "file missing ".$opt{file};
}
my $new_content = '';
open(my $ifh, '<'.$opt{file}) or die 'Houston, problem with "'.$opt{file}.'" for reading';
while (<$ifh>) {
if (/^Version:/) {
$_ = 'Version: '.$opt{version}.''."\n";
}
$new_content.= $_;
}
close($ifh);
open(my $ofh, '>'.$opt{file}) or die 'Houston, problem with "'.$opt{file}.'" for writing';
print {$ofh} $new_content;
close($ofh);
@@ -0,0 +1,340 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
define('PHPWG_ROOT_PATH', '../');
//Add a Clone piwigo from github//
// Usage : php test_piwigo.php --url "localhost/piwigo" --db_user "root" --db_password "password" --db_name "database" --file "picture.png"
$option = getopt("", array('url:', 'db_user:', 'db_password:', 'db_name:', 'file:', 'drop_db:'));
//Check mandatory option and test to perfom.
//For example : php test_piwigo.php --user "user" --password "123" --db_name "db123" --install "true"
$mandatory_fields = array(
'url',
'db_user',
'db_password',
);
foreach ($mandatory_fields as $field) {
if (!isset($option[$field])) {
die ('Missing --'.$field);
}
}
$option['url'] = 'http://'.$option['url'];
//Creat cookie file
$cookies = dirname(__DIR__).'/cookies.txt';
// Connection to mySQL
$mysqli = new mysqli('localhost', $option['db_user'], $option['db_password']);
if (!$mysqli) {
die ('Cannot connect to mySQL');
}
// Check if database name is set otherwise we use a random name.
// Then we create the database.
$option['db_name'] = create_database($option);
install_piwigo($option);
$pwg_token = log_user($option, $cookies);
create_album($option, $cookies);
add_picture($option, $cookies, $pwg_token);
//+-----------------------+
//| Create a new database |
//+-----------------------+
function create_database($option)
{
global $mysqli;
if (!isset($option['db_name'])) {
$option['db_name'] = uniqid();
}
$query = '
SHOW DATABASES
;';
$res = $mysqli->query($query);
while (($row = $res->fetch_row())) {
if ($row[0] == $option['db_name']) {
die ('Database name already exist');
}
}
$query = '
CREATE DATABASE '.$option['db_name'].'
;';
$mysqli->query($query);
return $option['db_name'];
}
//+--------------------------+
//| Script Installing Piwigo |
//+--------------------------+
function install_piwigo($option)
{
$data = array(
'install' => 1,
'dbhost' => 'localhost',
'dbuser' => $option['db_user'],
'dbpasswd' => $option['db_password'],
'dbname' => $option['db_name'],
'prefix' => 'piwigo_',
'admin_name' => 'admin',
'admin_pass1' => 'pwg123',
'admin_pass2' => 'pwg123',
'admin_mail' => 'test@gmail.com',
);
$ch = curl_init();
$curLopt = array(
CURLOPT_URL => $option['url'].'/install.php',
CURLOPT_COOKIESESSION => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $data,
);
curl_setopt_array($ch, $curLopt);
$content = curl_exec($ch);
$err = curl_errno($ch);
$errmsg = curl_error($ch);
$response = curl_getinfo($ch);
curl_close($ch);
sleep(2);
require_once(PHPWG_ROOT_PATH.'/local/config/database.inc.php');
if (PHPWG_INSTALLED === true) {
echo "Installation OK!\n";
}
else {
echo "Installation KO!\n";
}
}
//+----------------------+
//| Script Login an User |
//+----------------------+
function log_user($option, $cookies)
{
//Log an user - Admin here
$data = array(
'method' => 'pwg.session.login',
'password' => 'pwg123',
'username' => 'admin',
);
$ch = curl_init();
$curLopt = array(
CURLOPT_URL => $option['url'].'/ws.php?format=json',
CURLOPT_COOKIEJAR => $cookies,
CURLOPT_COOKIEFILE => $cookies,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $data,
);
curl_setopt_array($ch, $curLopt);
$content = curl_exec($ch);
$err = curl_errno($ch);
$errmsg = curl_error($ch);
$response = curl_getinfo($ch);
curl_close($ch);
//Gets information about the current session
$data = array(
'method' => 'pwg.session.getStatus',
);
$ch = curl_init();
$curLopt = array(
CURLOPT_URL => $option['url'].'/ws.php?format=json',
CURLOPT_COOKIEJAR => $cookies,
CURLOPT_COOKIEFILE => $cookies,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $data,
);
curl_setopt_array($ch, $curLopt);
$content = curl_exec($ch);
$err = curl_errno($ch);
$errmsg = curl_error($ch);
$response = curl_getinfo($ch);
curl_close($ch);
$result = json_decode($content, true);
if ($result['stat'] == 'ok') {
echo "Login OK!\n";
}
else {
echo "Login KO!\n";
}
return $result['result']['pwg_token'];
}
//+-----------------------+
//| Script Creating Album |
//+-----------------------+
function create_album($option, $cookies)
{
$data = array(
'method' => 'pwg.categories.add',
'name' => 'AlbumExample',
);
$ch = curl_init();
$curLopt = array(
CURLOPT_URL => $option['url'].'/ws.php?format=json',
CURLOPT_COOKIEJAR => $cookies,
CURLOPT_COOKIEFILE => $cookies,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $data,
);
curl_setopt_array($ch, $curLopt);
$content = curl_exec($ch);
$err = curl_errno($ch);
$errmsg = curl_error($ch);
$response = curl_getinfo($ch);
curl_close($ch);
$result = json_decode($content, true);
if ($result['stat'] == 'ok') {
echo "Album creation OK!\n";
}
else {
echo "Album creation KO!\n";
}
}
//+-------------------------+
//| Script adding picture |
//+-------------------------+
function add_picture($option, $cookies, $pwg_token)
{
global $mysqli;
exec("perl piwigo_upload.pl --url=".$option['url']." --user=admin --password=pwg123 --file=temp.png --album_id=1");
$mysqli->select_db($option['db_name']);
$query = '
SELECT count(*)
FROM piwigo_images
;';
$res = $mysqli->query($query);
if (($row = $res->fetch_row())[0] > 0) {
echo "Add a Picture OK!\n";
}
else {
echo "Add a picture KO!\n";
}
/*$content = readfile($option['file']);
$content_lenght = strlen($content);
$nb_chunks = ceil($content_lenght / 500);
$chunk_pos = 0;
$chunk_id = 0;
while ($chunk_pos < $content_lenght)
{
$chunk = substr($content, $chunk_pos, 500);
}
$chunk_path = '/tmp/'.md5($option['file']).'.chunk';
$chunk_pos += 500;*/
/*if (function_exists('curl_file_create'))
{
$cFile = curl_file_create($option['file']);
}
else
{
$cFile = '@'.realpath($option['file']);
}
$data = array(
'method' => 'pwg.images.upload',
//'name' => $option['file'],
//'chunk' => $chunk_id,
//'chunks' => $nb_chunks,
'category' => 1,
'file_contents' => $cFile,
'pwg_token' => $pwg_token,
);
$ch = curl_init();
$curLopt = array(
CURLOPT_URL => $option['url'].'/ws.php?format=json',
//CURLOPT_HTTPHEADER => $headers,
CURLOPT_COOKIEJAR => $cookies,
CURLOPT_COOKIEFILE => $cookies,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $data,
);
curl_setopt_array($ch, $curLopt);
$content = curl_exec($ch);
$err = curl_errno($ch);
$errmsg = curl_error($ch);
$response = curl_getinfo($ch);
curl_close($ch);
$result = json_decode($content);
print_r($result);
print_r($response);*/
}
if (isset($option['drop_db']) && $option['drop_db'] == true) {
$query = '
DROP DATABASE '.$option['db_name'].'
;';
$mysqli->query($query);
}
$mysqli->close();
?>
@@ -0,0 +1,154 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
define('PHPWG_ROOT_PATH', '../');
include_once( PHPWG_ROOT_PATH.'include/common.inc.php' );
include_once( PHPWG_ROOT_PATH.'tools/language/translation_validated.inc.php' );
$languages = array_keys(get_languages());
sort($languages);
$page['ref_compare'] = 'en_UK';
$page['ref_default_values'] = 'en_UK';
if (!isset($_GET['lang']))
{
echo '<a href="?lang=all">All languages</a><br><br>';
echo '<ul>';
foreach ($languages as $language)
{
if ($page['ref_compare'] == $language)
{
continue;
}
echo '<li><a href="?lang='.$language.'">'.$language.'</a></li>';
}
echo '</ul>';
exit();
}
else if (in_array($_GET['lang'], $languages))
{
$languages = array($_GET['lang']);
}
$file_list = array('common', 'admin', 'install', 'upgrade');
$metalang = array();
// preload reference languages
$metalang[ $page['ref_compare'] ] = load_metalang($page['ref_compare'], $file_list);
$metalang[ $page['ref_default_values'] ] = load_metalang($page['ref_default_values'], $file_list);
foreach ($languages as $language)
{
if (in_array($language, array($page['ref_compare'], $page['ref_default_values'])))
{
continue;
}
echo '<h2>'.$language.'</h2>';
$metalang[$language] = load_metalang($language, $file_list);
foreach ($file_list as $file)
{
if (isset($metalang[ $language ][$file]))
{
$missing_keys = array_diff(
array_keys($metalang[ $page['ref_compare'] ][$file]),
array_keys($metalang[ $language ][$file])
);
$output_missing = '';
foreach ($missing_keys as $key)
{
$output_missing.= get_line_to_translate($file, $key);
}
// strings not "really" translated?
$output_duplicated = '';
$output_lost = '';
foreach (array_keys($metalang[$language][$file]) as $key)
{
$exceptions = array('Level 0');
if (in_array($key, $exceptions))
{
continue;
}
if (isset($validated_keys[$language]) and in_array($key, $validated_keys[$language]))
{
continue;
}
$local_value = $metalang[$language][$file][$key];
if (!isset($metalang[ $page['ref_default_values'] ][$file][$key]))
{
$output_lost.= '#'.$key.'# does not exist in the reference language'."\n";
}
else
{
$ref_value = $metalang[ $page['ref_default_values'] ][$file][$key];
if ($local_value == $ref_value)
{
$output_duplicated.= get_line_to_translate($file, $key);
}
}
}
echo '<h3>'.$file.'.lang.php</h3>';
if ('' != $output_missing or '' != $output_duplicated)
{
$output = '';
if ('' != $output_missing)
{
$output.= "// missing translations\n".$output_missing;
}
if ('' != $output_duplicated)
{
$output.= "\n// untranslated yet\n".$output_duplicated;
}
echo '<textarea style="width:100%;height:250px;">'.$output.'</textarea>';
}
if ('' != $output_lost)
{
echo '<pre>'.$output_lost.'</pre>';
}
}
else
{
echo '<h3>'.$file.'.lang.php is missing</h3>';
}
}
}
function load_metalang($language, $file_list)
{
global $lang, $user;
$metalang = array();
foreach ($file_list as $file)
{
$lang = array();
$user['language'] = $language;
if (load_language($file.'.lang', '', array('language'=>$language, 'no_fallback'=>true)))
{
$metalang[$file] = $lang;
}
}
return $metalang;
}
function get_line_to_translate($file, $key)
{
global $metalang, $page;
$print_key = str_replace("'", '\\\'', $key);
$print_value = str_replace("'", '\\\'', $metalang[ $page['ref_default_values'] ][$file][$key]);
return '$'."lang['".$print_key."'] = '".$print_value."';\n";
}
?>
File diff suppressed because it is too large Load Diff
+206
View File
@@ -0,0 +1,206 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Piwigo web API (web-services) explorer</title>
<link rel="stylesheet" href="//cdn.jsdelivr.net/tiptip/1.3/tipTip.css">
<link rel="stylesheet" href="../admin/themes/default/fontello/css/fontello.css">
<link rel="stylesheet" href="ws/ws.css">
<link rel="stylesheet" href="ws/jquery.json-viewer.css">
<script src="../themes/default/js/jquery.min.js"></script>
<script src="../themes/default/js/jquery.cookie.js"></script>
<script src="../themes/default/js/plugins/jquery.tipTip.minified.js"></script>
<script src="ws/jquery.json-viewer.js"></script>
<script src="ws/ws.js"></script>
</head>
<body>
<div id="the_body">
<a name="top"></a>
<i class="darkModeButton icon-moon-inv" title="Toogle Dark Mode"></i>
<div id="the_header">
<a title="Go to admin page" href="../admin.php"><img src="ws/piwigo-logo-minimal.svg"></a>
<h1>Piwigo web API (web-services) explorer</h1>
</div> <!-- the_header -->
<div id="the_container">
<div id="the_methods">
<h2>Available methods</h2>
<div id="search">
<i class="icon-search"></i>
<input type="text" placeholder="Search">
</div>
<div id="methodsList">
</div>
</div> <!-- the_methods -->
<div id="the_page">
<div id="the_title">
<h2 id="methodName" style="display:none;"></h2>
<span id="onlys"></span>
</div>
<h2 id="errorWrapper" style="display:none;"></h2>
<div id="the_content">
<form id="urlForm" style="display:none;">
<input type="text" name="ws_url" size="60">
<input type="submit" value="Go!">
</form>
<div class="card" id="introMessage">
<h3 class="card-title"><i class="icon-info-circled-1"></i>What is this page ?</h3>
<div class="card-content">
<p>
<b>API = Application Programming Interface.</b><br>
This is the way other applications can communicate with Piwigo. This feature is also know as Web Services.
</p>
<p>Examples:</p>
<ul>
<li>Wordpress (web blog software) can display random photos from a Piwigo gallery in its sidebar</li>
<li>Lightroom (photo management software for desktop) can create albums and upload photos to Piwigo</li>
</ul>
<p>
This page lists all API methods available on your Piwigo installation, part of the Piwigo core or added by third-party plugins.
For each method you can consult required and optional parameters, and even test them in direct live!
</p>
<p class="header-description"> Introduced in Piwigo 16, you can now use an API key in the HTTP header
to perform authenticated requests without a user session.
For more details, check out our <a href="https://github.com/Piwigo/Piwigo/wiki/Piwigo-Web-API#api-key-authentication" target="_blank">documentation</a>.
</p>
<p>
For more information you can consult our Wiki <a href="https://github.com/Piwigo/Piwigo/wiki#web-api" target="_blank">Piwigo Web API</a> and <a href="https://piwigo.org/forum" target="_blank">our forums</a>.
</p>
</div>
</div> <!-- introMessage -->
<form id="methodWrapper" style="display:none;">
<div class="card" id="methodDescription" style="display:none;">
<h3 class="card-title"><i class="icon-book"></i>Description</h3>
<blockquote>
</blockquote>
</div> <!-- methodDescription -->
<div id="methodControl">
<div class="methodControlContainer">
<div class="card" id="methodParams">
<h3 class="card-title"><i class="icon-equalizer"></i>Method parameters</h3>
<div class="card-content">
<table>
<thead>
<tr>
<td>Name</td>
<td class="mini">Type</td>
<td>Value</td>
<td class="mini">Send</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
<span class="no-params" style="display: none;">This method takes no parameters</span>
</div>
</div> <!-- methodParams -->
</div> <!-- methodControlContainer -->
<div class="methodControlContainer">
<div class="card" id="testForm">
<h3 class="card-title"><i class="icon-wrench"></i>Test</h3>
<div class="card-content">
<div class="header-setting">
<p class="header-label">X-PIWIGO-API:</p>
<p class="header-warning">Doesn't work when you use "INVOKE (new window)"</p>
<input type="text" id="apiKey" placeholder="pkid-xxxxxxxx-xxxxxxxxxxxxxxxxxxxx:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" />
</div>
<div class="select-group">
<label for='requestFormat'>Request format</label>
<div class="select">
<select id="requestFormat">
<option value="get" selected>GET</option>
<option value="post">POST</option>
</select>
</div>
</div>
<div class='select-group'>
<label for='responseFormat'>Response format</label>
<div class="select">
<select id="responseFormat">
<option value="json" selected>JSON</option>
<option value="rest">REST (xml)</option>
<option value="php">PHP serial</option>
<option value="xmlrpc">XML RPC</option>
</select>
</div>
</div>
<div class="testAction">
<a href="#iframe-bottom" class="button" id="invokeMethod">INVOKE</a>
<a href="#" class="button" id="invokeMethodBlank">INVOKE (new window)</a>
</div>
</div>
</div> <!-- testForm -->
</div> <!-- methodControlContainer -->
</div> <!-- methodControl -->
<div class="card-2" id="requestURLDisplay" style="display:none;">
<h3 class="card-title"><i class="icon-network"></i>Request</h3>
<div class="card-content">
<blockquote>
<pre class="url"></pre>
<pre class="params"></pre>
</blockquote>
</div>
</div> <!-- requestDisplay -->
<div class="card-2" id="requestResultDisplay" style="display:none;">
<h3 class="card-title"><i class="icon-code"></i>Result</h3>
<div class="card-content">
<div id="resultWrapper">
<iframe src="" id="invokeFrame" name="invokeFrame"></iframe>
<pre id="json-viewer"></pre>
</div>
<div id="iframeAction">
<a href="#iframe-bottom" id="increaseIframe"><i class="icon-down-open"></i> increase height</a>
<a href="#iframe-bottom" id="decreaseIframe"><i class="icon-down-open"></i> decrease height</a>
<span id="iframe-bottom"></span>
</div>
</div>
</div>
</form> <!-- resultWrapper -->
<!-- hidden form for POST submition -->
<form method="post" action="" target="" id="invokeForm" style="display:none;"></form>
</div> <!-- the_content -->
</div> <!-- the_page -->
</div> <!-- the_container -->
<div id="the_footer">
Copyright &copy; 2002-2025 <a href="http://piwigo.org">Piwigo Team</a>
</div> <!-- the_footer -->
</div>
</body>
</html>
@@ -0,0 +1,57 @@
/* Root element */
.json-document {
padding: 1em 2em;
}
/* Syntax highlighting for JSON objects */
ul.json-dict, ol.json-array {
list-style-type: none;
margin: 0 0 0 1px;
border-left: 1px dotted #ccc;
padding-left: 2em;
}
.json-string {
color: #0B7500;
}
.json-literal {
color: #4B31FF;
font-weight: bold;
}
/* Toggle button */
a.json-toggle {
position: relative;
color: inherit;
text-decoration: none;
}
a.json-toggle:focus {
outline: none;
}
a.json-toggle:before {
font-size: 1.1em;
color: #c0c0c0;
content: "\25BC"; /* down arrow */
position: absolute;
display: inline-block;
width: 1em;
text-align: center;
line-height: 1em;
left: -1.2em;
}
a.json-toggle:hover:before {
color: #aaa;
}
a.json-toggle.collapsed:before {
/* Use rotated down arrow, prevents right arrow appearing smaller than down arrow in some browsers */
transform: rotate(-90deg);
}
/* Collapsable placeholder links */
a.json-placeholder {
color: #aaa;
padding: 0 1em;
text-decoration: none;
}
a.json-placeholder:hover {
text-decoration: underline;
}
@@ -0,0 +1,158 @@
/**
* jQuery json-viewer
* @author: Alexandre Bodelot <alexandre.bodelot@gmail.com>
* @link: https://github.com/abodelot/jquery.json-viewer
*/
(function($) {
/**
* Check if arg is either an array with at least 1 element, or a dict with at least 1 key
* @return boolean
*/
function isCollapsable(arg) {
return arg instanceof Object && Object.keys(arg).length > 0;
}
/**
* Check if a string represents a valid url
* @return boolean
*/
function isUrl(string) {
var urlRegexp = /^(https?:\/\/|ftps?:\/\/)?([a-z0-9%-]+\.){1,}([a-z0-9-]+)?(:(\d{1,5}))?(\/([a-z0-9\-._~:/?#[\]@!$&'()*+,;=%]+)?)?$/i;
return urlRegexp.test(string);
}
/**
* Transform a json object into html representation
* @return string
*/
function json2html(json, options) {
var html = '';
if (typeof json === 'string') {
// Escape tags and quotes
json = json
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/'/g, '&apos;')
.replace(/"/g, '&quot;');
if (options.withLinks && isUrl(json)) {
html += '<a href="' + json + '" class="json-string" target="_blank">' + json + '</a>';
} else {
// Escape double quotes in the rendered non-URL string.
json = json.replace(/&quot;/g, '\\&quot;');
html += '<span class="json-string">"' + json + '"</span>';
}
} else if (typeof json === 'number') {
html += '<span class="json-literal">' + json + '</span>';
} else if (typeof json === 'boolean') {
html += '<span class="json-literal">' + json + '</span>';
} else if (json === null) {
html += '<span class="json-literal">null</span>';
} else if (json instanceof Array) {
if (json.length > 0) {
html += '[<ol class="json-array">';
for (var i = 0; i < json.length; ++i) {
html += '<li>';
// Add toggle button if item is collapsable
if (isCollapsable(json[i])) {
html += '<a href class="json-toggle"></a>';
}
html += json2html(json[i], options);
// Add comma if item is not last
if (i < json.length - 1) {
html += ',';
}
html += '</li>';
}
html += '</ol>]';
} else {
html += '[]';
}
} else if (typeof json === 'object') {
var keyCount = Object.keys(json).length;
if (keyCount > 0) {
html += '{<ul class="json-dict">';
for (var key in json) {
if (Object.prototype.hasOwnProperty.call(json, key)) {
html += '<li>';
var keyRepr = options.withQuotes ?
'<span class="json-string">"' + key + '"</span>' : key;
// Add toggle button if item is collapsable
if (isCollapsable(json[key])) {
html += '<a href class="json-toggle">' + keyRepr + '</a>';
} else {
html += keyRepr;
}
html += ': ' + json2html(json[key], options);
// Add comma if item is not last
if (--keyCount > 0) {
html += ',';
}
html += '</li>';
}
}
html += '</ul>}';
} else {
html += '{}';
}
}
return html;
}
/**
* jQuery plugin method
* @param json: a javascript object
* @param options: an optional options hash
*/
$.fn.jsonViewer = function(json, options) {
// Merge user options with default options
options = Object.assign({}, {
collapsed: false,
rootCollapsable: true,
withQuotes: false,
withLinks: true
}, options);
// jQuery chaining
return this.each(function() {
// Transform to HTML
var html = json2html(json, options);
if (options.rootCollapsable && isCollapsable(json)) {
html = '<a href class="json-toggle"></a>' + html;
}
// Insert HTML in target DOM element
$(this).html(html);
$(this).addClass('json-document');
// Bind click on toggle buttons
$(this).off('click');
$(this).on('click', 'a.json-toggle', function() {
var target = $(this).toggleClass('collapsed').siblings('ul.json-dict, ol.json-array');
target.toggle();
if (target.is(':visible')) {
target.siblings('.json-placeholder').remove();
} else {
var count = target.children('li').length;
var placeholder = count + (count > 1 ? ' items' : ' item');
target.after('<a href class="json-placeholder">' + placeholder + '</a>');
}
return false;
});
// Simulate click on toggle button when placeholder is clicked
$(this).on('click', 'a.json-placeholder', function() {
$(this).siblings('a.json-toggle').click();
return false;
});
if (options.collapsed == true) {
// Trigger click to collapse all nodes
$(this).find('a.json-toggle').click();
}
});
};
})(jQuery);
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 117.19922 125.20118"
xml:space="preserve"
sodipodi:docname="piwigo-logo-minimal.svg"
width="117.19922"
height="125.20118"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata
id="metadata950"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs948" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1017"
id="namedview946"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.5789474"
inkscape:cx="113.68333"
inkscape:cy="114"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="Symbole_24_1"
inkscape:pagecheckerboard="0" />
<style
type="text/css"
id="style935">
.st0{fill:#656565;}
</style>
<g
id="Symbole_24_1"
transform="translate(-590,-460.7992)">
<path
id="Ellipse_68"
style="fill:#ffffff;fill-opacity:1"
d="m 108.69922,14.283203 c -13.600002,0.3 -12.199611,8.201172 -43.599611,8.201172 -31.4,-0.1 -7.00039,0 -7.90039,0 H 44 c -17.1,0 -31,13.9 -31,31 v 55.000005 c 0,17.09999 13.9,31 31,31 h 55.099609 c 17.100001,0 31.000001,-13.90001 31.000001,-31 V 37.283203 c 0.0647,-0.658884 0.0996,-1.325459 0.0996,-2 -0.1,-11.6 -9.9,-21 -21.5,-21 z m 0.5,13.201172 c 4.1,0 7.40039,3.300391 7.40039,7.400391 0,4.1 -3.40039,7.398437 -7.40039,7.398437 -4.1,0 -7.39844,-3.298437 -7.39844,-7.398437 0,-4.1 3.29844,-7.400391 7.39844,-7.400391 z M 71.599609,46.283203 c 19.2,0 34.701171,15.501172 34.701171,34.701172 0,19.100005 -15.501171,34.699215 -34.701171,34.699215 -19.2,0 -34.699218,-15.49921 -34.699218,-34.699215 0,-19.2 15.499218,-34.701172 34.699218,-34.701172 z M 71.328125,56.384766 A 24.6,24.6 0 0 0 47,80.984375 24.6,24.6 0 0 0 71.599609,105.58398 24.6,24.6 0 0 0 96.199219,80.984375 24.6,24.6 0 0 0 71.599609,56.384766 a 24.6,24.6 0 0 0 -0.271484,0 z"
transform="translate(577,446.516)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

+633
View File
@@ -0,0 +1,633 @@
/* BEGIN CSS RESET
http://meyerweb.com/eric/tools/css/reset
v2.0 | 20110126 | License: none (public domain) */
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li,
fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video
{margin:0;padding:0;border:0;font-size:100%;vertical-align:baseline;}
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {display:block;}
body {line-height:1.1;}
blockquote, q {quotes:none;}
blockquote:before, blockquote:after, q:before, q:after {content:'';content:none;}
table {border-collapse:collapse;border-spacing:0;}
/* END CSS RESET */
#the_body, body {
--color-bg: #E5E5E5;
--color-bg-secondary: #FFFFFF;
--color-text: #434343;
--color-action: #FF7700;
--color-action-text: #FFF;
--color-action-hover: #ee4b00;
--color-action-secondary: #eee;
--color-action-secondary-text: var(--color-text);
--color-action-secondary-hover: #ddd;
--color-bg-nuance:#f7f7f7;
--border-radius: 5px;
--box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.25);
--header-heigth: 50px;
--footer-heigth: 20px;
--container-heigth: calc(100vh - var(--header-heigth) - var(--footer-heigth));
background: var(--color-bg);
}
#the_body.dark-mode {
--color-bg: #393939;
--color-bg-secondary: #242424;
--color-text: #fff;
--color-action: #FF7700;
--color-action-text: #FFF;
--color-action-hover: #ee4b00;
--color-action-secondary: #181818;
--color-action-secondary-text: #fff;
--color-action-secondary-hover: #292929;
--color-bg-nuance:#1e1e1e;
--box-shadow: none;
}
li {
list-style: none;
}
html {font-family:"Corbel","Lucida Grande","Verdana",sans-serif;color:#434343;font-size:14px;}
#the_body {
display: flex;
flex-direction: column;
}
#the_container {
display: grid;
grid-template-columns: 250px auto;
}
#the_header, #the_footer {
display: flex;
align-items: center;
z-index: 10;
overflow: hidden;
background: var(--color-bg-secondary);
color: var(--color-text);
}
a {
color:var(--color-action);
text-decoration:none;
}
a:hover {
color:var(--color-action-hover);
border-bottom-width:1px;
}
blockquote {
padding:8px;
}
hr {
margin:10px 30px;
}
ul {
margin-left:25px;
}
p {margin: 8px 0;}
h1 {
font-size:20px;
padding-left:10px;
}
h2 {
font-size:16px;
padding: 10px 10px 5px 10px;
}
h2#errorWrapper {
color:#F42C00;
font-weight:normal;
}
h3 {
display:inline-block;
font-weight:bold;
}
input[type="text"] {
border: 2px solid var(--color-action-secondary);
border-radius: var(--border-radius);
color: var(--color-text);
background: var(--color-bg-secondary);
width: 100%;
padding: 5px;
}
#the_header {
height: var(--header-heigth);
box-shadow: var(--box-shadow);
}
#the_header img {
width: 30px;
opacity: 1;
margin-left: 10px;
}
#the_body:not(.dark-mode) #the_header img {
filter: brightness(80%);;
}
#the_footer {
height: var(--footer-heigth);
justify-content: center;
background: var(--color-bg-secondary);
opacity: 0.7;
}
#the_footer a {
margin-left: 5px;
}
#the_methods, #the_page {
height: var(--container-heigth);
overflow-y: auto;
overflow-x: hidden;
/* ScrollBar customization for firefox */
scrollbar-width: thin;
}
#the_methods {
background-color: var(--color-bg-secondary);
color: var(--color-text);
box-shadow: var(--box-shadow);
z-index: 5;
}
#methodsList, #search {
font-size:1.1em;
margin:5px 10px;
position: relative;
}
#search {
display: flex;
}
#search i {
position:absolute;
top:50%;
left:5px;
transform: translateY(-50%);
}
#search input {
padding-left: 25px;
}
.method-node {
position: relative;
display: flex;
flex-direction: column;
}
.method-node input {
opacity: 0;
position: absolute;
width: 0;
height: 0;
}
.method-node-content {
padding-left: 30px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.method-node label, .method-link {
margin: 5px 0px;
overflow-x: hidden;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
overflow-y: clip;
}
.method-link {
order: 1;
}
.method-node label {
background: var(--color-action-secondary);
color: var(--color-action-secondary-text);
padding: 6px;
border-radius: var(--border-radius);
font-weight: bold;
}
.onSearch .method-node label {
pointer-events: none;
padding-left: 10px;
}
.onSearch .method-node label i {
display: none;
}
.method-node label i::before {
font-size: 12px;
transform: rotate(-90deg);
transition: 0.2s ease-in-out;
}
.method-node > input:checked ~ label i::before {
transform: rotate(0deg);
}
.method-node label:hover {
background-color: var(--color-action-secondary-hover);
}
#methodsList > .method-node > label {
background: var(--color-action);
color: var(--color-action-text);
}
#methodsList > .method-node > label:hover {
background: var(--color-action-hover);
}
#the_page {
background-color: var(--color-bg);
color: var(--color-text);
}
#the_title {
display: flex;
align-items: baseline;
}
#the_title #onlys .only {
border-radius: var(--border-radius);
background: var(--color-action-secondary);
color: var(--color-text);
padding: 5px;
margin-right: 10px;
}
#the_content {
padding:10px;
padding-top: 0px;
}
#methodWrapper {
display: flex;
flex-direction: column;
}
#methodControl {
display: grid;
grid-template-columns: 66% 34%;
}
#methodDescription blockquote ul {
margin-top: 10px;
}
#methodDescription blockquote ul li {
list-style-type: disc;
}
.card, .card-2 {
margin: 10px;
background-color: var(--color-bg-secondary);
border-radius: var(--border-radius);
position: relative;
}
.card {
padding:10px;
}
.card-2 {
border: 2px solid var(--color-action);
margin-top: 25px;
}
.card .card-title {
font-size: 16px;
}
.card-2 .card-title {
font-size: 14px;
color: var(--color-action);
position: absolute;
top: 0;
transform: translateY(calc(-100% - 5px));
}
.card-2 .card-content {
overflow-y: auto;
/* firefox scrollbar customization */
scrollbar-width: thin;
}
.card .card-title i {
color: var(--color-action);
font-size: 20px;
margin-right: 5px;
}
.card .card-content {
padding: 10px;
position: relative;
}
.header-setting {
margin-bottom: 10px;
}
.header-setting input {
width: 98%;
}
.header-description {
margin: 0;
margin-bottom: 10px;
}
.header-warning {
margin: 0;
color: red;
font-size: 10px;
font-style: italic;
}
.header-label {
margin-bottom: 0;
}
/* #requestResultDisplay {
background: white;
} */
#methodParams table {
width: 100%;
}
#methodParams td .methodParameterSend{
opacity: 0;
position: absolute;
width: 0;
height: 0;
}
#methodParams td .methodParameterSendCheckbox {
padding: 10px;
position: relative;
border: 2px solid var(--color-action);
border-radius: var(--border-radius);
line-height: 0;
box-sizing: border-box;
cursor: pointer;
}
#methodParams td .methodParameterSendCheckbox i {
color: var(--color-action-text);
position:absolute;
top:50%;
left:50%;
transform: translate(-50%,-50%);
}
#methodParams td .methodParameterSend:checked ~ .methodParameterSendCheckbox {
background: var(--color-action);
}
#methodParams td .methodParameterSend:not(:checked) ~ .methodParameterSendCheckbox i {
display: none;
transform: translate(-50%,-50%);
}
#methodParams tr {
display: flex;
border-radius: var(--border-radius);
align-items: center;
height: 38px;
}
#methodParams tr td {
display: flex;
flex-wrap: nowrap;
padding: 0px 12px;
}
#methodParams tr .required {
color: var(--color-action);
font-size: 20px;
}
#methodParams tr td:nth-child(1){width: calc(50% - 100px);}
#methodParams tr td:nth-child(2){width: 100px;}
#methodParams tr td:nth-child(3){width: calc(50% - 30px);}
#methodParams tr td:nth-child(4){width: 30px; justify-content: center;}
#methodParams thead tr {
background: var(--color-action);
color: var(--color-action-text);
font-weight: bold;
}
#methodParams tbody tr:nth-child(even) {
background-color: var(--color-bg-nuance);
}
#methodParams .type-badge {
display:flex;
overflow: hidden;
align-items: center;
justify-content: center;
width:20px;
height:20px;
font-size: 20px;
font-weight: bold;
line-height:16px;
border-radius: 100%;
background: var(--color-action);
color: var(--color-action-text);
margin-right: 2px;
}
#methodParams .type-badge::before {
font-size: 12px;
}
#testForm .card-content .select-group {
margin-bottom: 10px;
display: flex;
align-items: baseline;
flex-direction: column;
}
#testForm .testAction {
display:flex;
justify-content: flex-end;
}
#testForm .testAction .button {
margin-left: 10px;
}
#testForm select, #testForm select::before, #testForm select::after {
box-sizing: border-box;
}
select {
appearance: none;
background-color: transparent;
border: none;
padding: 0 1em 0 0;
margin: 0;
width: 100%;
font-family: inherit;
font-size: inherit;
cursor: inherit;
line-height: inherit;
color: var(--color-text);
}
#testForm .select {
width: 100%;
outline: none;
min-width: 15ch;
max-width: 30ch;
border: 2px solid var(--color-action-secondary);
border-radius: var(--border-radius);
padding: 5px;
cursor: pointer;
font-weight: bold;
position: relative;
}
#testForm .select::after {
content: '\e835';
font-family: 'fontello';
font-size: 12px;
color: var(--color-text);
position:absolute;
top:50%;
right: 10px;
transform: translateY(-50%);
pointer-events: none;
}
/* Remove arrow from select */
#testForm select::-ms-expand {
display: none;
}
#introMessage {
font-size:1.1em;
}
#introMessage .card-content {
padding: 0 10px;
}
#urlForm {
margin-bottom:10px;
}
a.button {
padding: 10px;
border-radius: var(--border-radius);
background: var(--color-action);
color: var(--color-action-text);
display: flex;
align-items: center;
}
a.button:hover {
background-color: var(--color-action-hover);
}
#tiptip_content {
font-size:12px;
}
#resultWrapper {
width:100%;
height:300px;
padding: 0;
position:relative;
}
iframe {width:100%;height:100%; background-color: white;}
#iframeAction {
position: absolute;
bottom: 0;
transform: translateY(calc(100% + 5px));
}
#decreaseIframe i::before {
transform: rotate(180deg);
}
div.onlys {padding:.25em .5em;display:table;border-radius:4px;margin-bottom:0.5em;}
.darkModeButton {
position: absolute;
z-index: 11;
top: 0px;
right: 0px;
width: var(--header-heigth);
height: var(--header-heigth);
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
opacity: 0.7;
cursor: pointer;
}
.darkModeButton:hover {
opacity: 1;
}
/* -- Tiptip customization -- */
#tiptip_content {
color: var(--color-action-text) !important;
background: var(--color-action) !important;
text-shadow: none;
}
#tiptip_holder.tip_bottom #tiptip_arrow_inner {
border-bottom-color: var(--color-action) !important;
}
/* -- Chrome ScrollBar customization -- */
::-webkit-scrollbar {
width: 8px;
}
/* Track */
::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.11);
}
/* Handle */
::-webkit-scrollbar-thumb {
background: var(--color-action);
border-radius:5px;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: var(--color-action);
}
+540
View File
@@ -0,0 +1,540 @@
$(() => {
// global lets
let cachedMethods = new Array;
let ws_url = "http://";
// automatic detection of ws_url
match = document.location.toString().match(/^(https?.*\/)tools\/ws\.html?/);
if (match == null) {
askForUrl();
}
else {
ws_url = match[1] + 'ws.php';
getMethodList();
}
// manual set of ws_url
$("#urlForm").submit(function () {
ws_url = $(this).children("input[name='ws_url']").val();
getMethodList();
return false;
});
// invoke buttons
$("#invokeMethod").click(function () {
invokeMethod($("#methodName").html(), false);
return false;
});
$("#invokeMethodBlank").click(function () {
invokeMethod($("#methodName").html(), true);
return false;
});
// resizable iframe
$("#increaseIframe").click(function () {
$("#resultWrapper").css('height', $("#resultWrapper").height() + 100);
});
$("#decreaseIframe").click(function () {
if ($("#resultWrapper").height() > 200) {
$("#resultWrapper").css('height', $("#resultWrapper").height() - 100);
}
});
// mask all wrappers
function resetDisplay() {
$("#errorWrapper").hide();
$("#methodWrapper").hide();
$("#methodName").hide();
$("#urlForm").hide();
$("#methodDescription blockquote").empty();
$("#methodDescription").hide();
$("#requestURLDisplay").hide();
$("#requestResultDisplay").hide();
$("#invokeFrame").attr('src', '');
}
// display error wrapper
function displayError(error) {
resetDisplay();
$("#errorWrapper").html("<b>Error:</b> " + error).show();
}
// display ws_url form
function askForUrl() {
displayError("can't contact web-services, please give absolute url to 'ws.php'");
if ($("#urlForm input[name='ws_url']").val() == "") {
$("#urlForm input[name='ws_url']").val(ws_url);
}
$("#urlForm").show();
}
// parse Piwigo JSON
function parsePwgJSON(json) {
try {
resp = jQuery.parseJSON(json);
if (resp == null | resp.result == null | resp.stat == null | resp.stat != 'ok') {
throw new Error();
}
}
catch (e) {
displayError("unable to parse JSON string");
resp = { "stat": "ko", "result": "null" };
}
return resp.result;
}
// fetch methods list
function getMethodList() {
resetDisplay();
$.ajax({
type: "GET",
url: ws_url,
data: { format: "json", method: "reflection.getMethodList" }
}).done(function (result) {
// for debug
//console.log(result);
result = parsePwgJSON(result);
if (result != null) {
methods = result.methods;
let methodTree = {};
for (let i = 0; i < methods.length; i++) {
addMethodToNode(methodTree, methods[i].split('.'))
}
$("#methodsList").html(displayMethodNode(methodTree, [])).show();
// trigger method selection
$("#methodsList .method-link").click(function () {
selectMethod($(this).data('method'));
});
if ($.cookie('wse-menu-state')) {
$.cookie('wse-menu-state').split(',').forEach(id => $(`input[id="${id}"]`).attr('checked', true));
}
setStateMenu();
$('.method-node-content').each((i, node) => {
let content = $(node);
let checkbox = content.parent().children('input');
checkbox.on('change', function() {
let id = checkbox.attr('id');
let menustate = $.cookie('wse-menu-state')?.split(',') ?? [];
if (this.checked) {
content.slideDown(200);
menustate.push(id)
} else {
content.slideUp(200);
menustate = menustate.filter(str => str !== id);
}
$.cookie('wse-menu-state', menustate.join(','))
})
})
}
}).error(function (jqXHR, textStatus, errorThrown) {
askForUrl();
});
}
function addMethodToNode(methodNode, methodRoute) {
if (methodRoute.length > 1) {
let node = methodRoute.shift();
if (!methodNode[node])
methodNode[node] = {};
addMethodToNode(methodNode[node], methodRoute);
} else
methodNode[methodRoute[0]] = 1;
}
function displayMethodNode(methodNode, route) {
let html = '';
if (methodNode === 1) {
html = `<a
class="method-link"
data-method="${route.join('.')}"
title="${route[route.length - 1]}"
>
${route[route.length - 1]}
</a>`
} else {
html = route.length === 0 ? '' : `<div class="method-node">
<input type="checkbox" id="method-node-input-${route.join('.')}">
<label for="method-node-input-${route.join('.')}" title="${route[route.length - 1]}">
<i class="icon-down-open"></i>
<span>${route[route.length - 1]}</span>
</label>
<div class="method-node-content">`;
for (const node in methodNode) {
html += displayMethodNode(methodNode[node], [...route, node]);
}
html += route.length === 0 ? '' :'</div></div>';
}
return html;
}
function setStateMenu() {
$('.method-node').each((i, n) => {
let node = $(n);
let content = node.children('.method-node-content')
let checkbox = node.children('input');
if (checkbox.prop('checked')) {
content.show();
} else {
content.hide();
}
})
}
// select method
function selectMethod(methodName) {
$("#introMessage").hide();
$("#tiptip_holder").fadeOut(200);
if (cachedMethods[methodName]) {
fillNewMethod(methodName);
}
else {
$.ajax({
type: "GET",
url: ws_url,
data: { format: "json", method: "reflection.getMethodDetails", methodName: methodName }
}).done(function (result) {
result = parsePwgJSON(result);
if (result != null) {
let onlys = [];
if (result.options.post_only || result.options.admin_only) {
if (result.options.post_only) {
onlys.push('POST only');
}
if (result.options.admin_only) {
onlys.push('Admin only');
}
}
result.onlys = onlys;
cachedMethods[methodName] = result;
fillNewMethod(methodName);
}
}).error(function (jqXHR, textStatus, errorThrown) {
displayError("unknown error");
});
}
}
// display method details
function fillNewMethod(methodName) {
resetDisplay();
method = cachedMethods[methodName];
$("#methodName").html(method.name).show();
$('#onlys').html('');
method.onlys.forEach((text) => {
$('#onlys').append($(`<span class="only">${text}</span>`));
})
if (method.description != "") {
$("#methodDescription blockquote").html(method.description);
$("#methodDescription").show();
}
$("#requestFormat").val(method.options.post_only ? 'post' : 'get');
let methodParams = '';
if (method.params && method.params.length > 0) {
$('.no-params').hide();
$("#methodParams table").show();
for (let i = 0; i < method.params.length; i++) {
let param = method.params[i],
isOptional = param.optional,
acceptArray = param.acceptArray,
defaultValue = param.defaultValue == null ? '' : param.defaultValue,
info = param.info == null ? '' : '<i class="methodInfo icon-info-circled-1" title="' + param.info.replace(/"/g, '&quot;') + '"></i>',
type = '',
subtype = '',
optional = '<span class="required" title = "This parameter is required" >*</span >',
array = '<span class="type-badge icon-clone" title="Can be an array"></span >';
if (param.type.match(/bool/)) type += '<span class="type-badge" title="Boolean">B<span>';
if (param.type.match(/int/)) type += '<span class="type-badge" title="Integer">I</span>';
if (param.type.match(/float/)) type += '<span class="type-badge" title="Float">F</span>';
if (param.type.match(/positive/)) subtype += '<span class="type-badge icon-plus" title="Positive"></span>';
if (param.type.match(/notnull/)) subtype += '<span class="type-badge" title="Not null"><span style="transform:translateY(-3px)">&oslash;</span></span>';
// if an array is direclty printed, the delimiter is a comma where we use a pipe
if (typeof defaultValue == 'object') {
defaultValue = defaultValue.join('|');
}
methodParams += `<tr>
<td>${param.name + (isOptional ? '' : optional ) + info }</td>
<td class="mini">${(acceptArray ? array : '') + type + subtype}</td>
<td class="input"><input type="text" class="methodParameterValue" data-id="${i}" value="${defaultValue}"></td>
<td class="mini">
<input type="checkbox" id="parameter-send-${i}" class="methodParameterSend" data-id="${i}" ${(isOptional ? '' : 'checked="checked"')}>
<label class="methodParameterSendCheckbox" for="parameter-send-${i}"><i class="icon-ok"></i></label>
</td>
</tr>`;
}
$("#methodParams tbody").html(methodParams);
}
else {
$('.no-params').show();
$("#methodParams table").hide();
}
$("#methodWrapper").show();
// trigger field modification
$("input.methodParameterValue").change(function () {
$("input.methodParameterSend[data-id='" + $(this).data('id') + "']").attr('checked', 'checked');
});
// tiptip
$(".methodInfo").tipTip({
maxWidth: "300px",
defaultPosition: "bottom",
delay: 0
});
$(".required, .type-badge").tipTip({
maxWidth: "100px",
defaultPosition: "bottom",
delay: 0
});
}
// invoke method
function invokeMethod(methodName, newWindow) {
$('#json-viewer').jsonViewer({});
$('#requestURLDisplay').show();
$('#requestResultDisplay').show();
let method = cachedMethods[methodName];
let reqUrl = ws_url + "?format=" + $("#responseFormat").val();
const isJson = $("#responseFormat").val() === 'json';
const authorization = $('#apiKey').val();
const useCookie = '' === authorization;
let fetchOption = {};
if (!useCookie) {
fetchOption.credentials = 'omit';
fetchOption.headers = {
"X-PIWIGO-API": authorization
}
}
// GET
if ($("#requestFormat").val() == 'get') {
reqUrl += "&method=" + methodName;
for (let i = 0; i < method.params.length; i++) {
if (!$("input.methodParameterSend[data-id='" + i + "']").is(":checked")) {
continue;
}
let paramValue = $("input.methodParameterValue[data-id='" + i + "']").val();
let paramSplitted = paramValue.split('|');
if (method.params[i].acceptArray && paramSplitted.length > 1) {
$.each(paramSplitted, function (v) {
reqUrl += '&' + method.params[i].name + '[]=' + paramSplitted[v];
});
}
else {
reqUrl += '&' + method.params[i].name + '=' + paramValue;
}
}
if (newWindow) {
window.open(reqUrl);
}
else {
fetch(reqUrl, fetchOption)
.then(data => data.text())
.then(data => {
showResponseData(data);
})
}
$('#requestURLDisplay').find('.url').html(reqUrl).end()
.find('.params').hide();
}
// POST
else {
let params = {};
let form = $("#invokeForm");
form.attr('action', reqUrl);
let t = '<input type="hidden" name="method" value="' + methodName + '">';
for (let i = 0; i < method.params.length; i++) {
if (!$("input.methodParameterSend[data-id='" + i + "']").is(":checked")) {
continue;
}
let paramValue = $("input.methodParameterValue[data-id='" + i + "']").val(),
paramName = method.params[i].name,
paramSplitted = paramValue.split('|');
if (method.params[i].acceptArray && paramSplitted.length > 1) {
params[paramName] = [];
$.each(paramSplitted, function (i, value) {
params[paramName].push(value);
t += '<input type="hidden" name="' + paramName + '[]" value="' + value + '">';
});
}
else {
params[paramName] = paramValue;
t += '<input type="hidden" name="' + paramName + '" value="' + paramValue + '">';
}
}
if (!newWindow) {
$("#invokeFrame").hide();
$('#json-viewer').show();
const formData = new URLSearchParams();
formData.append('method', methodName);
for (const key in params) {
formData.append(key, params[key]);
}
fetchOption.headers ??= {};
fetchOption.headers['Content-Type'] = 'application/x-www-form-urlencoded';
fetch(reqUrl, {
...fetchOption,
method: 'POST',
body: formData
})
.then(data => {
return data.text();
})
.then(data => {
showResponseData(data);
});
} else {
$("#invokeFrame").show();
$('#json-viewer').hide();
form.html(t);
form.attr('target', newWindow ? "_blank" : "invokeFrame");
form.submit();
}
$('#requestURLDisplay').find('.url').html(reqUrl).end()
.find('.params').show().html(JSON.stringify(params, null, 4));
}
return false;
}
$('#search input').val('');
$('#search input').on('input', function () {
if ($(this).val()) {
$('.method-node, .method-link').hide();
if (!$('#methodsList').hasClass('onSearch')) {
$('#methodsList').addClass('onSearch');
$('.method-node-content').show();
}
function showBranch(methodNode) {
methodNode.show();
while (methodNode.parent().parent().hasClass("method-node")) {
methodNode = methodNode.parent().parent();
methodNode.show();
}
}
$('.method-link').each((i, n) => {
if ($(n).data('method').toLowerCase().search($(this).val().toLowerCase())!= -1) {
showBranch($(n));
}
})
} else {
$('.method-node, .method-link').show();
$('#methodsList').removeClass('onSearch');
setStateMenu()
}
})
if ($.cookie('wse-dark-mode')) {
$('#the_body').addClass('dark-mode');
$('.darkModeButton').addClass('icon-sun-inv');
}
$('.darkModeButton').click(() => {
if ($.cookie('wse-dark-mode')) {
$('.darkModeButton').removeClass('icon-sun-inv').addClass('icon-moon-inv');
$.removeCookie('wse-dark-mode');
$('#the_body').removeClass('dark-mode');
} else {
$('.darkModeButton').removeClass('icon-moon-inv').addClass('icon-sun-inv');
$.cookie('wse-dark-mode', true);
$('#the_body').addClass('dark-mode');
}
})
})
function showResponseData(data) {
const isJson = $("#responseFormat").val() === 'json';
if (isJson) {
try {
const json = JSON.parse(data);
$('#json-viewer').jsonViewer(json);
$("#invokeFrame").hide();
$('#json-viewer').show();
} catch (error) {
const iframe = $('#invokeFrame');
const iframeDoc = iframe[0].contentDocument || iframe[0].contentWindow.document;
iframeDoc.open();
iframeDoc.write(`<pre>${data}</pre>`);
iframeDoc.close();
$("#invokeFrame").show();
$('#json-viewer').hide();
}
return;
}
const iframe = $('#invokeFrame');
const iframeDoc = iframe[0].contentDocument || iframe[0].contentWindow.document;
iframeDoc.open();
iframeDoc.write(data);
iframeDoc.close();
$("#invokeFrame").show();
$('#json-viewer').hide();
}