Debug modulebuilder
This commit is contained in:
parent
4f75b6d656
commit
8db4e91888
@ -58,7 +58,7 @@ class DolEditor
|
|||||||
* 'Out:name' share toolbar into the div called 'name'
|
* 'Out:name' share toolbar into the div called 'name'
|
||||||
* @param boolean $toolbarstartexpanded Bar is visible or not at start
|
* @param boolean $toolbarstartexpanded Bar is visible or not at start
|
||||||
* @param int $uselocalbrowser Enabled to add links to local object with local browser. If false, only external images can be added in content.
|
* @param int $uselocalbrowser Enabled to add links to local object with local browser. If false, only external images can be added in content.
|
||||||
* @param int $okforextendededitor True=Allow usage of extended editor tool (like fckeditor)
|
* @param int $okforextendededitor True=Allow usage of extended editor tool (like fckeditor). If false, use simple textarea.
|
||||||
* @param int $rows Size of rows for textarea tool
|
* @param int $rows Size of rows for textarea tool
|
||||||
* @param string $cols Size of cols for textarea tool (textarea number of cols '70' or percent 'x%')
|
* @param string $cols Size of cols for textarea tool (textarea number of cols '70' or percent 'x%')
|
||||||
* @param int $readonly 0=Read/Edit, 1=Read only
|
* @param int $readonly 0=Read/Edit, 1=Read only
|
||||||
@ -100,7 +100,7 @@ class DolEditor
|
|||||||
$this->editor->Height = $height;
|
$this->editor->Height = $height;
|
||||||
if (! empty($width)) $this->editor->Width = $width;
|
if (! empty($width)) $this->editor->Width = $width;
|
||||||
$this->editor->ToolbarSet = $shorttoolbarname; // Profile of this toolbar set is deinfed into theme/mytheme/ckeditor/config.js
|
$this->editor->ToolbarSet = $shorttoolbarname; // Profile of this toolbar set is deinfed into theme/mytheme/ckeditor/config.js
|
||||||
$this->editor->Config['AutoDetectLanguage'] = 'true';
|
$this->editor->Config['AutoDetectLanguage'] = 'true'; // Language of user (browser)
|
||||||
$this->editor->Config['ToolbarLocation'] = $toolbarlocation ? $toolbarlocation : 'In';
|
$this->editor->Config['ToolbarLocation'] = $toolbarlocation ? $toolbarlocation : 'In';
|
||||||
$this->editor->Config['ToolbarStartExpanded'] = $toolbarstartexpanded;
|
$this->editor->Config['ToolbarStartExpanded'] = $toolbarstartexpanded;
|
||||||
|
|
||||||
|
|||||||
@ -335,7 +335,7 @@ class Interfaces
|
|||||||
$triggers[$j]['iscoreorexternal'] = $iscoreorexternal[$key];
|
$triggers[$j]['iscoreorexternal'] = $iscoreorexternal[$key];
|
||||||
$triggers[$j]['version'] = $objMod->getVersion();
|
$triggers[$j]['version'] = $objMod->getVersion();
|
||||||
$triggers[$j]['status'] = img_picto($langs->trans("Active"),'tick');
|
$triggers[$j]['status'] = img_picto($langs->trans("Active"),'tick');
|
||||||
if ($disabledbyname > 0 || $disabledbymodule > 1) $triggers[$j]['status'] = " ";
|
if ($disabledbyname > 0 || $disabledbymodule > 1) $triggers[$j]['status'] = '';
|
||||||
|
|
||||||
$text ='<b>'.$langs->trans("Description").':</b><br>';
|
$text ='<b>'.$langs->trans("Description").':</b><br>';
|
||||||
$text.=$objMod->getDesc().'<br>';
|
$text.=$objMod->getDesc().'<br>';
|
||||||
|
|||||||
@ -15,7 +15,7 @@ ModuleBuilderDescspecifications=You can enter here a long text to describe the s
|
|||||||
ModuleBuilderDescobjects=Define here the objects you want to manage with your module. A sql file, a page to list them, to create/edit/view a card and an API will be generated.
|
ModuleBuilderDescobjects=Define here the objects you want to manage with your module. A sql file, a page to list them, to create/edit/view a card and an API will be generated.
|
||||||
ModuleBuilderDescmenus=This tab is dedicated to define menu entries provided by your module.
|
ModuleBuilderDescmenus=This tab is dedicated to define menu entries provided by your module.
|
||||||
ModuleBuilderDescpermissions=This tab is dedicated to define the new permissions you want to provide with your module.
|
ModuleBuilderDescpermissions=This tab is dedicated to define the new permissions you want to provide with your module.
|
||||||
ModuleBuilderDesctriggers=This is the view of triggers provided by your module. To include code executed when a triggered business event is launched, just edit this file with your IDE.
|
ModuleBuilderDesctriggers=This is the view of triggers provided by your module. To include code executed when a triggered business event is launched, just edit this file.
|
||||||
ModuleBuilderDeschooks=This tab is dedicated to hooks.
|
ModuleBuilderDeschooks=This tab is dedicated to hooks.
|
||||||
ModuleBuilderDescwidgets=This tab is dedicated to manage/build widgets.
|
ModuleBuilderDescwidgets=This tab is dedicated to manage/build widgets.
|
||||||
ModuleBuilderDescbuildpackage=You can generate here a "ready to distribute" package file (a normalized .zip file) of your module and a "ready to distribute" documentation file. Just click on button to build the package or documentation file.
|
ModuleBuilderDescbuildpackage=You can generate here a "ready to distribute" package file (a normalized .zip file) of your module and a "ready to distribute" documentation file. Just click on button to build the package or documentation file.
|
||||||
@ -24,7 +24,7 @@ EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All files relat
|
|||||||
DangerZone=Danger zone
|
DangerZone=Danger zone
|
||||||
BuildPackage=Build package/documentation
|
BuildPackage=Build package/documentation
|
||||||
BuildDocumentation=Build documentation
|
BuildDocumentation=Build documentation
|
||||||
ModuleIsNotActive=This module was not activated yet (go into Home-Setup-Module to make it live)
|
ModuleIsNotActive=This module was not activated yet (go into %s to make it live)
|
||||||
ModuleIsLive=This module has been activated. Any change on it may break a current active feature.
|
ModuleIsLive=This module has been activated. Any change on it may break a current active feature.
|
||||||
DescriptionLong=Long description
|
DescriptionLong=Long description
|
||||||
EditorName=Name of editor
|
EditorName=Name of editor
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Copyright (C) 2001-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
|
/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
|
||||||
* Copyright (C) 2005-2010 Regis Houssin <regis.houssin@capnetworks.com>
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -24,6 +22,7 @@
|
|||||||
|
|
||||||
require '../main.inc.php';
|
require '../main.inc.php';
|
||||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
||||||
|
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
|
||||||
|
|
||||||
$langs->load("admin");
|
$langs->load("admin");
|
||||||
$langs->load("modulebuilder");
|
$langs->load("modulebuilder");
|
||||||
@ -31,17 +30,20 @@ $langs->load("other");
|
|||||||
|
|
||||||
$action=GETPOST('action','aZ09');
|
$action=GETPOST('action','aZ09');
|
||||||
$confirm=GETPOST('confirm','alpha');
|
$confirm=GETPOST('confirm','alpha');
|
||||||
|
|
||||||
$module=GETPOST('module','alpha');
|
$module=GETPOST('module','alpha');
|
||||||
$tab=GETPOST('tab','aZ09');
|
$tab=GETPOST('tab','aZ09');
|
||||||
$tabobj=GETPOST('tabobj','alpha');
|
$tabobj=GETPOST('tabobj','alpha');
|
||||||
if (empty($module)) $module='initmodule';
|
if (empty($module)) $module='initmodule';
|
||||||
if (empty($tab)) $tab='description';
|
if (empty($tab)) $tab='description';
|
||||||
if (empty($tabobj)) $tabobj='newobject';
|
if (empty($tabobj)) $tabobj='newobject';
|
||||||
|
$file=GETPOST('file','alpha');
|
||||||
|
|
||||||
$modulename=dol_sanitizeFileName(GETPOST('modulename','alpha'));
|
$modulename=dol_sanitizeFileName(GETPOST('modulename','alpha'));
|
||||||
$objectname=dol_sanitizeFileName(GETPOST('objectname','alpha'));
|
$objectname=dol_sanitizeFileName(GETPOST('objectname','alpha'));
|
||||||
|
|
||||||
// Security check
|
// Security check
|
||||||
|
if (empty($conf->modulebuilder->enabled)) accessforbidden('ModuleBuilderNotAllowed');
|
||||||
if (! $user->admin && empty($conf->global->MODULEBUILDER_FOREVERYONE)) accessforbidden('ModuleBuilderNotAllowed');
|
if (! $user->admin && empty($conf->global->MODULEBUILDER_FOREVERYONE)) accessforbidden('ModuleBuilderNotAllowed');
|
||||||
|
|
||||||
|
|
||||||
@ -373,6 +375,29 @@ if ($dirins && $action == 'generatepackage')
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($action == 'savefile')
|
||||||
|
{
|
||||||
|
$pathoftrigger=dol_buildpath($file, 0);
|
||||||
|
$pathoftriggerbackup=dol_buildpath($file.'.back', 0);
|
||||||
|
|
||||||
|
dol_move($pathoftrigger, $pathoftriggerbackup, 0, 1, 0, 0);
|
||||||
|
|
||||||
|
$content = GETPOST('triggerfilecontent');
|
||||||
|
|
||||||
|
// Save file on disk
|
||||||
|
$newmask = 0;
|
||||||
|
|
||||||
|
file_put_contents($pathoftrigger, $content);
|
||||||
|
if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK;
|
||||||
|
if (empty($newmask)) // This should no happen
|
||||||
|
{
|
||||||
|
$newmask='0664';
|
||||||
|
}
|
||||||
|
|
||||||
|
@chmod($pathoftrigger, octdec($newmask));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* View
|
* View
|
||||||
@ -568,7 +593,8 @@ elseif (! empty($module))
|
|||||||
|
|
||||||
$modulelowercase=strtolower($module);
|
$modulelowercase=strtolower($module);
|
||||||
|
|
||||||
$modulestatusinfo=img_info('').' '.$langs->trans("ModuleIsNotActive");
|
$urltomodulesetup='<a href="'.DOL_URL_ROOT.'/admin/modules.php?search_keyword='.urlencode($module).'">'.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").'</a>';
|
||||||
|
$modulestatusinfo=img_info('').' '.$langs->trans("ModuleIsNotActive", $urltomodulesetup);
|
||||||
if (! empty($conf->$module->enabled))
|
if (! empty($conf->$module->enabled))
|
||||||
{
|
{
|
||||||
$modulestatusinfo=img_warning().' '.$langs->trans("ModuleIsLive");
|
$modulestatusinfo=img_warning().' '.$langs->trans("ModuleIsLive");
|
||||||
@ -882,12 +908,15 @@ elseif (! empty($module))
|
|||||||
$interfaces = new Interfaces($db);
|
$interfaces = new Interfaces($db);
|
||||||
$triggers = $interfaces->getTriggersList(array('/'.strtolower($module).'/core/triggers'));
|
$triggers = $interfaces->getTriggersList(array('/'.strtolower($module).'/core/triggers'));
|
||||||
|
|
||||||
|
if ($action != 'editfile' || empty($file))
|
||||||
|
{
|
||||||
print '<div class="div-table-responsive-no-min">';
|
print '<div class="div-table-responsive-no-min">';
|
||||||
print '<table class="noborder">
|
print '<table class="noborder">
|
||||||
<tr class="liste_titre">
|
<tr class="liste_titre">
|
||||||
<td colspan="2">'.$langs->trans("File").'</td>
|
<td colspan="2">'.$langs->trans("File").'</td>
|
||||||
<td align="center">'.$langs->trans("Active").'</td>
|
<td align="center">'.$langs->trans("Active").'</td>
|
||||||
<td align="center"> </td>
|
<td align="center"> </td>
|
||||||
|
<td align="center"> </td>
|
||||||
</tr>
|
</tr>
|
||||||
';
|
';
|
||||||
|
|
||||||
@ -895,21 +924,47 @@ elseif (! empty($module))
|
|||||||
foreach ($triggers as $trigger)
|
foreach ($triggers as $trigger)
|
||||||
{
|
{
|
||||||
print '<tr class="oddeven">';
|
print '<tr class="oddeven">';
|
||||||
print '<td valign="top" width="14" align="center">'.$trigger['picto'].'</td>';
|
print '<td width="14" align="center">'.$trigger['picto'].'</td>';
|
||||||
print '<td class="tdtop">'.$trigger['relpath'].'</td>';
|
print '<td>'.$trigger['relpath'].'</td>';
|
||||||
print '<td valign="top" align="center">'.$trigger['status'].'</td>';
|
print '<td align="center">'.(empty($trigger['status'])?$langs->trans("No"):$trigger['status']).'</td>';
|
||||||
print '<td class="tdtop">';
|
print '<td class="tdtop">';
|
||||||
$text=$trigger['info'];
|
$text=$trigger['info'];
|
||||||
$text.="<br>\n<strong>".$langs->trans("File")."</strong>:<br>\n".$trigger['relpath'];
|
$text.="<br>\n<strong>".$langs->trans("File")."</strong>:<br>\n".$trigger['relpath'];
|
||||||
//$text.="\n".$langs->trans("ExternalModule",$trigger['isocreorexternal']);
|
//$text.="\n".$langs->trans("ExternalModule",$trigger['isocreorexternal']);
|
||||||
print $form->textwithpicto('', $text);
|
print $form->textwithpicto('', $text);
|
||||||
print '</td>';
|
print '</td>';
|
||||||
|
print '<td>';
|
||||||
|
print '<a href="'.$_SERVER['PHP_SELF'].'?tab='.$tab.'&module='.$module.'&action=editfile&file='.urlencode($trigger['relpath']).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
|
||||||
|
print '</td>';
|
||||||
print '</tr>';
|
print '</tr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
print '</table>';
|
print '</table>';
|
||||||
print '</div>';
|
print '</div>';
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$pathoftrigger=dol_buildpath($file, 0);
|
||||||
|
|
||||||
|
$content = file_get_contents($pathoftrigger);
|
||||||
|
|
||||||
|
// New module
|
||||||
|
print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
|
||||||
|
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
|
||||||
|
print '<input type="hidden" name="action" value="savefile">';
|
||||||
|
print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
|
||||||
|
print '<input type="hidden" name="tab" value="'.$tab.'">';
|
||||||
|
print '<input type="hidden" name="module" value="'.$module.'">';
|
||||||
|
|
||||||
|
$doleditor=new DolEditor('triggerfilecontent', $content, '', '600', 'Full', 'In', true, false, false, 0, '90%');
|
||||||
|
print $doleditor->Create(1, '', false);
|
||||||
|
print '<center>';
|
||||||
|
print '<input type="submit" class="button" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
|
||||||
|
print '</center>';
|
||||||
|
|
||||||
|
print '</form>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($tab == 'widgets')
|
if ($tab == 'widgets')
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Copyright (C) ---Put here your own copyright and developer email---
|
/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
|
* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Copyright (C) ---Put here your own copyright and developer email---
|
/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
|
* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
# DO NOT DELETE THIS FILE MANUALLY
|
# DO NOT DELETE THIS FILE MANUALLY
|
||||||
# If this file exists, it means the class and file for object MyOjbect was generated by ModuleBuilder. Use ModuleBuilder if you want to delete object.
|
# If this file exists, it means the class and file for object MyOjbect was generated by ModuleBuilder. So prefer to use ModuleBuilder if you want to delete object.
|
||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Copyright (C) ---Put here your own copyright and developer email---
|
/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
|
* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Copyright (C) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
|
/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
* Copyright (C) ---Put here your own copyright and developer email---
|
* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/* <one line to give the program's name and a brief idea of what it does.>
|
/* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
* Copyright (C) <year> <name of author>
|
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/* <one line to give the program's name and a brief idea of what it does.>
|
/* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
* Copyright (C) <year> <name of author>
|
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Copyright (C) 2007-2015 Laurent Destailleur <eldy@users.sourceforge.net>
|
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
* Copyright (C) ---Put here your own copyright and developer email---
|
* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Copyright (C) 2007-2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
* Copyright (C) ---Put here your own copyright and developer email---
|
* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env php
|
#!/usr/bin/env php
|
||||||
<?php
|
<?php
|
||||||
/* Copyright (C) 2007-2013 Laurent Destailleur <eldy@users.sourceforge.net>
|
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
* Copyright (C) ---Put here your own copyright and developer email---
|
* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
-- <one line to give the program's name and a brief idea of what it does.>
|
-- Copyright (C) ---Put here your own copyright and developer email---
|
||||||
-- Copyright (C) <year> <name of author>
|
|
||||||
--
|
--
|
||||||
-- This program is free software: you can redistribute it and/or modify
|
-- 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
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/* <one line to give the program's name and a brief idea of what it does.>
|
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
* Copyright (C) <year> <name of author>
|
* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/* <one line to give the program's name and a brief idea of what it does.>
|
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
* Copyright (C) <year> <name of author>
|
* Copyright (C) ---Put here your own copyright and developer email---
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user