Your IP : 216.73.216.190


Current Path : /proc/1908984/root/proc/2603263/cwd/
Upload File :
Current File : //proc/1908984/root/proc/2603263/cwd/aimyindexnow.tar

aimyindexnow.php000064400000023746152354740050010011 0ustar00<?php
/*
 * Copyright (c) 2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          http://www.aimy-extensions.com/software-license.html
 */
 defined( '_JEXEC' ) or die(); require_once( __DIR__ . '/notifier.php' ); require_once( __DIR__ . '/helpers/ComponentInfoHelper.php' ); require_once( __DIR__ . '/helpers/ComponentDataHelper.php' ); require_once( __DIR__ . '/helpers/PluginHelper.php' ); require_once( __DIR__ . '/helpers/StorageHelper.php' ); require_once( __DIR__ . '/helpers/ExcludePatternHelper.php' ); use Aimy\IndexNow\Notifier; use Aimy\IndexNow\Helpers\ComponentInfoHelper; use Aimy\IndexNow\Helpers\ComponentDataHelper; use Aimy\IndexNow\Helpers\PluginHelper; use Aimy\IndexNow\Helpers\StorageHelper; use Aimy\IndexNow\Helpers\ExcludePatternHelper; use Joomla\CMS\Factory; use Joomla\CMS\Uri\Uri; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Language\Text; use Joomla\CMS\Session\Session; class plgContentAimyIndexNow extends CMSPlugin { protected $autoloadLanguage = true; protected $app; public function __construct( $subject, $config = array() ) { parent::__construct( $subject, $config ); if ( ! $this->shouldRun() ) { return; } if ( $this->params->get( 'mode', 'ask' ) == 'ask' && ( PluginHelper::inBackend() or PluginHelper::isFrontendEditing() ) ) { Factory::getDocument() ->addScript( Uri::root( true ) . '/media/plg_aimyindexnow/submit.js' ) ->addStyleDeclaration( '#AimyIndexNow-send{margin-left:24px;}' . '#AimyIndexNow-send.active{background: transparent url("' . Uri::root( true ) . '/media/plg_aimyindexnow/wait.gif' . '") no-repeat center center !important;' . 'min-width:24px;min-height:24px;border:0;}' . '.AimyIndexNow-rv div{margin:6px 0;}' . '.AimyIndexNow-rv > div.success:first-child::after{' . 'content:"\2713";color:#390;' . 'font-size:2em;margin-left:12px;}' . '.AimyIndexNow-rv .error::after{content:"\274C";color:#F80;' . 'font-size:1.2em;margin-left:12px;}' . '.AimyIndexNow-rv .notice::after{content:"\2757";' . 'color:#F90;font-size:1.2em;margin-left:12px;}' ); } if ( ! PluginHelper::isJoomla3() && $this->app->input->get( 'option', '' ) != 'com_media' ) { $sess = Factory::getSession(); if ( $sess && $sess->has( 'msgs', 'AimyIndexNow' ) ) { $msgs = $sess->get( 'msgs', false, 'AimyIndexNow' ); if ( $msgs && is_array( $msgs ) && ! empty( $msgs ) ) { foreach ( $msgs as $queue => $qMsgs ) { foreach ( $qMsgs as $i => $msg ) { $this->app->enqueueMessage( $msg, $queue ); } } } $sess->clear( 'msgs', 'AimyIndexNow' ); } } } public function onContentAfterSave( $context, $article, $isNew ) { if ( ! $this->shouldRun() ) { return; } return $this->handle( $context, $article ); } public function onContentChangeState( $context, $ids, $state ) { if ( ! $this->shouldRun() ) { return; } if ( ! $this->hasContextSupportEnabled( $context ) ) { return; } foreach ( $ids as $i => $id ) { if ( ( $data = ComponentDataHelper::get( $context, $id ) ) ) { $this->handle( $context, $data ); } else { $this->queueMessage( '<b>Aimy IndexNow</b>: ' . 'Failed to get data for item #' . $id, 'error' ); } } } public function handle( $context, &$data ) { if ( ! $this->hasContextSupportEnabled( $context ) ) { return; } $page = ComponentInfoHelper::get( $context, $data ); if ( ! $page or ! $page->path ) { return false; } if ( ! $page->isPublished or ! $page->isPublic ) { return false; } if ( isset( $page->robots ) && ! empty( $page->robots ) ) { if ( stripos( $page->robots, 'noindex' ) !== false ) { return false; } } if ( $patterns = $this->params->get( "exclude-patterns", false ) ) { $match = ExcludePatternHelper::matches( explode( "\n", $patterns ), $page->path ); if ( $match !== false ) { $this->queueMessage( '<b>Aimy IndexNow</b>: ' . JText::sprintf( 'AIMY_IN_URL_EXCLUDED_BY_PATTERN_XY', $page->url, $match ), 'notice' ); return false; } } $mode = $this->params->get( 'mode', 'ask' ); if ( $mode == 'off' ) { return $this->passUrlToSitemap( $page ); } if ( ( $lastSubmit = StorageHelper::get( $page->path ) ) ) { $elapsed = PluginHelper::getElapsedMinutes( $lastSubmit ); $interval = $this->params->get( 'min-submit-interval', 10 ); if ( $elapsed <= $interval ) { $this->queueMessage( '<b>Aimy IndexNow</b>: ' . Text::sprintf( 'AIMY_IN_URL_SUBMITTED_X_MINUTES_AGO', $elapsed ), 'notice' ); return false; } } if ( $this->params->get( 'disable-local', true ) ) { $ip = PluginHelper::getWebsiteIpAddress(); if ( $ip && PluginHelper::isLocalIpAddress( $ip ) ) { $this->queueMessage( '<b>Aimy IndexNow</b>: ' . Text::sprintf( 'AIMY_IN_NOTIFICATION_SKIPPED_LOCAL_IP', $ip ), 'info' ); return false; } } if ( $mode == 'auto' ) { return $this->submit( $page ); } return $this->showNotificationSendable( $page ); } public function submit( $page ) { if ( ! is_object( $page ) or ! isset( $page->url ) ) { throw new \RuntimeException( '<b>Aimy IndexNow</b>: invalid page data' ); } $key = false; try { $key = $this->getApiKey(); } catch ( \Exception $e ) { $this->queueMessage( '<b>Aimy IndexNow</b>: ' . $e->getMessage(), 'error' ); return false; } $this->passUrlToSitemap( $page ); try { Notifier::submitSingleUrl( $page->url, $key ); $this->queueMessage( '<b>Aimy IndexNow</b>: ' . Text::sprintf( 'AIMY_IN_NOTIFICATION_SENT_X', $page->url ) ); StorageHelper::set( $page->path, time() ); } catch ( \Exception $e ) { $this->queueMessage( '<b>Aimy IndexNow</b>: ' . $e->getMessage(), 'error' ); return false; } return true; } public function getApiKey() { $key = trim( $this->params->get( 'key', '' ) ); PluginHelper::checkKey( $key ); if ( PluginHelper::writeKeyfileIfNotExistent( $key ) ) { $this->queueMessage( '<b>Aimy IndexNow</b>: ' . Text::sprintf( 'AIMY_IN_KEYFILE_X_WRITTEN', PluginHelper::getKeyfileName( $key ) ), 'notice' ); } return $key; } private function showNotificationSendable( $page ) { $key = false; try { $key = $this->getApiKey(); } catch ( \Exception $e ) { $this->queueMessage( $e->getMessage(), 'error' ); return false; } $pageData = rawurlencode( json_encode( $page ) ); $this->queueMessage( '<b>Aimy IndexNow</b>: ' . Text::sprintf( 'AIMY_IN_NOTIFICATION_SENDABLE_X', $page->url, '<button class="btn btn-primary" id="AimyIndexNow-send" ' . 'data-page="' . $pageData . '" ' . 'data-key="' . $key . '">' . Text::_( 'AIMY_IN_NOTIFICATION_SEND_NOW' ) . '</button>' ) ); } private function shouldRun() { if ( $this->isEmbeddedInFrame() ) { return false; } if ( ! ( PluginHelper::inBackend() or PluginHelper::isFrontendEditing() ) ) { return false; } return true; } private function isEmbeddedInFrame() { $tmpl = $this->app->input->get( 'tmpl', false, 'word' ); if ( $tmpl && $tmpl == 'component' ) { $comp = $this->app->input->get( 'option', false, 'word' ); if ( ! $comp or $comp != 'com_media' ) { return true; } } return false; } private function hasContextSupportEnabled( $context ) { $comp = PluginHelper::getCtxComponent( $context ); return $this->params->get( 'support-' . $comp, false ); } private function queueMessage( $msg, $queue = 'notice' ) { if ( PluginHelper::isJoomla3() ) { $this->app->enqueueMessage( $msg, $queue ); } else { if ( $this->app->input->get( 'option' ) == 'com_media' ) { $sess = Factory::getSession(); $msgs = $sess->get( 'msgs', [], 'AimyIndexNow' ); if ( ! isset( $msgs[ $queue ] ) ) { $msgs[ $queue ] = []; } $msgs[ $queue ][] = $msg; $sess->set( 'msgs', $msgs, 'AimyIndexNow' ); } else { $this->app->enqueueMessage( $msg, $queue ); } } } private function passUrlToSitemap( $page ) { if ( ! $this->params->get( 'pass-to-sitemap', false ) ) { return false; } try { require_once( __DIR__ . '/sitemap.php' ); $rv = Aimy\IndexNow\Sitemap::addOrUpdateURL( $page ); $msg = false; if ( $rv == Aimy\IndexNow\Sitemap::URL_ADDED ) { $msg = Text::sprintf( 'AIMY_IN_AIMY_SITEMAP_ADDED_X', $page->path ); } elseif ( $rv == Aimy\IndexNow\Sitemap::URL_UPDATED ) { $msg = Text::sprintf( 'AIMY_IN_AIMY_SITEMAP_UPDATED_X', $page->path ); } if ( $msg ) { $this->queueMessage( '<b>Aimy IndexNow &rarr; Aimy Sitemap</b>: ' . $msg ); } if ( $this->params->get( 'write-sitemap', false ) ) { Aimy\IndexNow\Sitemap::writeXMLSitemap(); } } catch( \Exception $e ) { $this->queueMessage( $e->getMessage(), 'error' ); return false; } return true; } public function onExtensionAfterSave( $context, $table, $isNew, $data = array() ) { if ( strpos( JVERSION, '3.' ) !== 0 ) { return; } if ( $context != 'com_plugins.plugin' or ! is_object( $table ) or ! property_exists( $table, 'element' ) or $table->element != 'aimyindexnow' ) { return; } if ( ! is_array( $data ) or empty( $data ) or ! isset( $data[ 'params' ] ) or ! is_array( $data[ 'params' ] ) or ! isset( $data[ 'params' ][ 'dl_key' ] ) ) { return; } $key = trim( $data[ 'params' ][ 'dl_key' ] ); require_once( __DIR__ . '/helpers/DownloadKeyHelper.php' ); try { AimyIndexNow\Helpers\DownloadKeyHelper::passKeyToUpdatesites( $key ); } catch ( Exception $e ) { Factory::getApplication( 'Failed to pass download key to update sites: ' . $e->getMessage(), 'error' ); } } public function onInstallerBeforePackageDownload( &$url, &$headers ) { if ( ! strpos( $url, 'aimy-extensions.com' ) or ! strpos( $url, '/plg_AimyIndexNow/' ) ) { return; } require_once( __DIR__ . '/helpers/DownloadKeyHelper.php' ); $rv = AimyIndexNow\Helpers\DownloadKeyHelper::validateKey(); if ( is_object( $rv ) && ! $rv->valid && isset( $rv->msg ) ) { Factory::getApplication()->enqueueMessage( '<b>Aimy IndexNow: ' . $rv->msg . '</b>', 'error' ); } } public function onAjaxAimyindexnow() { if ( ! Session::checkToken() ) { throw new \RuntimeException( '<b>Aimy IndexNow</b>: ' . Text::_( 'JINVALID_TOKEN' ) ); } $key = $this->app->input->post->get( 'key', false, 'string' ); if ( $this->getApiKey() != $key ) { throw new \RuntimeException( '<b>Aimy IndexNow</b>: Key mismatch: ' . $key ); } $page = false; try { $page = json_decode( rawurldecode( $this->app->input->post->get( 'page', false, 'string' ) ), false ); if ( ! $page or ! is_object( $page ) ) { throw new \RuntimeException( 'No page data retrieved' ); } } catch ( \Exception $e ) { throw new \RuntimeException( '<b>Aimy IndexNow</b>: ' . $e->getMessage() ); } if ( ! $this->submit( $page ) ) { throw new \RuntimeException(); } return true; } } 
notifier.php000064400000003553152354740050007107 0ustar00<?php
/* Copyright (c) 2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          http://www.aimy-extensions.com/software-license.html
 */
 namespace Aimy\IndexNow; defined( '_JEXEC' ) or die(); use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Language\Text; use Joomla\CMS\Uri\Uri; abstract class Notifier { static private $endpoint = 'https://api.indexnow.org/indexnow'; const MAX_URLS_PER_POST = 10000; static public function submitSingleUrl( $contentUrl, $key ) { $url = self::$endpoint . sprintf( '?url=%s&key=%s', rawurlencode( $contentUrl ), $key ); $resp = HttpFactory::getHttp()->get( $url, array(), 5 ); if ( $resp->code !== 200 && $resp->code !== 202 ) { throw new \RuntimeException( Text::sprintf( 'AIMY_IN_ERR_HTTP_RESPONSE_X', $resp->code, self::getCause( $resp->code ) ) ); } return true; } static public function submitMultipleUrls( $contentUrls, $key ) { if ( ! count( $contentUrls ) ) { return 0; } $d = new \StdClass(); $d->host = Uri::getInstance()->getHost(); $d->key = $key; $d->urlList = array(); $offset = 0; do { $d->urlList = array_slice( $contentUrls, $offset, self::MAX_URLS_PER_POST ); $offset += count( $d->urlList ); $resp = HttpFactory::getHttp()->post( self::$endpoint, json_encode( $d ), array( 'Content-Type' => 'application/json; charset=utf-8' ) ); if ( $resp->code !== 200 && $resp->code !== 202 ) { throw new \RuntimeException( Text::sprintf( 'AIMY_IN_ERR_HTTP_RESPONSE_X', $resp->code, self::getCause( $resp->code ) ) ); } } while ( $offset < count( $contentUrls ) ); return $offset; } static private function getCause( $code ) { switch ( $code ) { case 400: return 'Bad request'; break; case 403: return 'Forbidden'; break; case 422: return 'Unprocessable entity'; break; case 429: return 'Too many requests'; break; } return 'Unknown'; } } 
info.php000064400000001046152354740050006216 0ustar00<?php
/*
 * Copyright (c) 2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          https://www.aimy-extensions.com/software-license.html
 */
 namespace Aimy\IndexNow; defined( '_JEXEC' ) or die(); abstract class Info { static public function getVersion() { return '6.0'; } static public function getProductURL() { return 'https://www.aimy-extensions.com/joomla/indexnow.html'; } static public function isPro() { return true ; } } 
sitemap.php000064400000005336152354740050006733 0ustar00<?php
/* Copyright (c) 2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          http://www.aimy-extensions.com/software-license.html
 */
 namespace Aimy\IndexNow; defined( '_JEXEC' ) or die(); use Joomla\CMS\Language\Text; use Joomla\CMS\Factory; abstract class Sitemap { static private $smLoaded = false; static private $robTxt = null; const REQUIRED_VERSION = '31.0'; const URL_ADDED = 1; const URL_UPDATED = 2; public static function loadAimySitemap() { $basedir = JPATH_ADMINISTRATOR . '/components/com_aimysitemap/'; $classes = array( 'helpers/info.php', 'Sitemap.php', 'Uri.php', 'RobotsTxt.php', 'ExcludePatterns.php' ); foreach ( $classes as $class ) { $path = $basedir . '/' . $class; if ( ! file_exists( $path ) ) { throw new \RuntimeException( '<b>Aimy IndexNow</b>: ' . Text::sprintf( 'AIMY_IN_ERR_AIMY_SITEMAP_NOT_FOUND_X', self::REQUIRED_VERSION ) ); } require_once( $path ); } $v = \AimySitemapInfo::getVersion(); if ( version_compare( $v, self::REQUIRED_VERSION, '<' ) ) { throw new \RuntimeException( '<b>Aimy IndexNow</b>: ' . Text::sprintf( 'AIMY_IN_ERR_AIMY_SITEMAP_NEEDS_UPDATE_XY', self::REQUIRED_VERSION, $v ) ); } } public static function writeXMLSitemap() { if ( ! self::$smLoaded ) { self::loadAimySitemap(); } try { $sm = new \AimySitemapSitemap(); Factory::getLanguage()->load( 'com_aimysitemap', JPATH_ADMINISTRATOR ); $rv = $sm->write_sitemap_file(); } catch ( \Exception $e ) { throw new \RuntimeException( '<b>Aimy IndexNow &rarr; Aimy Sitemap</b>: ' . $e->getMessage() ); } } public static function addOrUpdateURL( $page ) { if ( ! self::$smLoaded ) { self::loadAimySitemap(); } try { $rt = new \AimySitemapRobotsTxt( self::$robTxt ); self::$robTxt = $rt->get_txt(); if ( $rt->disallowed( $page->path ) ) { throw new \RuntimeException( Text::sprintf( 'AIMY_IN_AIMY_SITEMAP_FORBIDDEN_BY_ROBOTS_TXT_X', $page->path ) ); } if ( \AimySitemapExcludePatterns::is_excluded( $page->path ) ) { throw new \RuntimeException( Text::sprintf( 'AIMY_IN_AIMY_SITEMAP_EXCLUDED_BY_PATTERN_XY', $page->path, \AimySitemapExcludePatterns::get_last_matching_pattern() ) ); } } catch ( \Exception $e ) { throw new \RuntimeException( '<b>Aimy IndexNow &rarr; Aimy Sitemap</b>: ' . $e->getMessage() ); } $o = new \StdClass(); $u = new \AimySitemapURI( $page->path ); $o->url = $u->getResource(); $o->lang = isset( $page->lang ) ? $page->lang : '*'; $o->title = isset( $page->title ) ? $page->title : ''; $o->mtime = time(); $rv = false; try { $sm = new \AimySitemapSitemap(); $rv = $sm->add_or_update_url( $o ); } catch ( \Exception $e ) { throw new \RuntimeException( '<b>Aimy IndexNow &rarr; Aimy Sitemap</b>: ' . $e->getMessage() ); } return $rv; } } 
index.html000064400000000016152354740050006543 0ustar00<html></html>
install-hints.php000064400000014645152354740050010065 0ustar00<?php
/*
 * Copyright (c) 2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          http://www.aimy-extensions.com/software-license.html
 */
 defined( '_JEXEC' ) or die(); use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Uri\Uri; use Joomla\CMS\Router\Route; use Joomla\Registry\Registry; class plgContentAimyIndexNowInstallerScript { const V_JOOMLA_MIN = '3.9'; const V_PHP_MIN = '5.3.10'; public function preflight( $type, $parent ) { return ( self::check_php_version( self::V_PHP_MIN ) && self::check_joomla_version( self::V_JOOMLA_MIN ) ); } public function postflight( $route, $adapter ) { $task = strtolower( $route ); if ( $task != 'install' && $task != 'update' ) { return; } if ( $task == 'update' ) { require_once( __DIR__ . '/helpers/UpdateServer.php' ); AimyIndexNowUpdateServer::cleanup_server_list( $adapter ); $files_to_remove = array( 'proonlynotice.php', 'indexnowkey.php', 'helpers.php', 'storage.php', 'exclude-patterns.php', 'componentinfo.php', 'componentdata.php' ); foreach ( $files_to_remove as $file ) { $path = JPATH_ROOT . '/plugins/content/aimyindexnow/' . $file; if ( file_exists( $path ) ) { File::delete( $path ); } } if ( strpos( JVERSION, '3.' ) !== 0 ) { try { self::deleteExtensionParam( 'dl_key' ); } catch ( Exception $e ) { error_log( 'AimyIndexNow: ' . $e->getMessage() ); } } } if ( $task == 'install' ) { Factory::getLanguage()->load( 'plg_content_aimyindexnow', JPATH_ADMINISTRATOR ); if ( ! empty( Uri::root( true ) ) ) { Factory::getApplication()->enqueueMessage( Text::sprintf( 'AIMY_IN_WARN_JOOMLA_IN_SUBDIRECTORY_X', 'https://www.aimy-extensions.com/joomla/indexnow.html#manual-joomla-installation-within-a-subdirectory' ), 'error' ); } echo '<div style="padding:32px;text-align:center;">', '<h1>', '<img src="', Uri::base(), '../media/plg_aimyindexnow/aimy-logo_340x327.png" ', 'width="340" height="327" alt="Aimy" />', '<br/>', 'Aimy IndexNow (PRO) v6.0', '</h1>', '<p class="lead">', Text::_( $task == 'update' ? 'AIMY_IN_HINT_UPDATED' : 'AIMY_IN_HINT_INSTALLED' ), '!', '</p>'; $cfg_url = false; $enabled = false; try { $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( array( 'extension_id', 'enabled' ) ) ) ->from( $db->quoteName( '#__extensions' ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( 'aimyindexnow' ) ) ->where( $db->quoteName( 'type' ) . ' = ' . $db->quote( 'plugin' ) ); $db->setQuery( $q ); $row = $db->loadObject(); if ( $row && $row->extension_id ) { $cfg_url = Route::_( 'index.php?' . 'option=com_plugins&task=plugin.edit&' . 'extension_id=' . $row->extension_id ); $enabled = $row->enabled; } } catch ( Exception $e ) {} echo '<p>'; if ( $cfg_url ) { echo self::_btn( $cfg_url, Text::_( ! $enabled ? 'AIMY_IN_HINT_ENABLE_CONFIGURE' : 'AIMY_IN_HINT_CONFIGURE' ) ), ' &nbsp; '; } echo self::_btn( 'https://www.aimy-extensions.com/joomla/indexnow.html#user-manual', Text::_( 'AIMY_IN_HINT_READ_MANUAL' ), true ), ' &nbsp; ', self::_btn( 'https://aimy-extensions.com/images/products/indexnow/plg-aimy-indexnow.pdf?v=6.0', Text::_( 'AIMY_IN_HINT_DL_MANUAL' ), false ), '</p>'; echo '<p style="padding:12px 0;" />', '<a href="https://www.aimy-extensions.com/joomla/indexnow.html" target="_blank">https://www.aimy-extensions.com/joomla/indexnow.html</a>', '</p>', '</div>', "\n"; try { $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( array( 'params' ) ) ) ->from( $db->quoteName( '#__extensions' ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( 'com_aimysitemap' ) ) ->where( $db->quoteName( 'type' ) . ' = ' . $db->quote( 'component' ) ); $db->setQuery( $q ); $smRow = $db->loadObject(); if ( $smRow && $smRow->params ) { require_once( 'helpers/PluginHelper.php' ); $smParams = Aimy\IndexNow\Helpers\PluginHelper ::jsonToObject( $smRow->params ); if ( isset( $smParams->crawl_exclude_patterns ) ) { $q = $db->getQuery( true ); $q->select( $db->quoteName( 'params' ) ) ->from( $db->quoteName( '#__extensions' ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( 'aimyindexnow' ) ); $db->setQuery( $q ); $inRow = $db->loadObject(); if ( $inRow && $inRow->params ) { $inParams = Aimy\IndexNow\Helpers\PluginHelper ::jsonToObject( $inRow->params ); $inParams->{"exclude-patterns"} = $smParams->crawl_exclude_patterns; $q = $db->getQuery( true ); $q->update( $db->quoteName( '#__extensions' ) ) ->set( $db->quoteName( 'params' ) . ' = ' . $db->quote( json_encode( $inParams ) ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( 'aimyindexnow' ) ); $db->setQuery( $q ); if ( $db->execute() ) { Factory::getApplication() ->enqueueMessage( Text::_( 'AIMY_IN_EXCLUDE_PATTERNS_IMPORTED' ), 'info' ); } } } } } catch ( Exception $e ) {} } } static private function _btn( $url, $text, $new_tab = false ) { return '<a class="btn btn-lg btn-success" href="' . $url . '" ' . ( $new_tab ? 'target="_blank" ' : '' ) . 'role="button" style="color:#FFF !important">' . $text . '!' . '</a>'; } static private function check_php_version( $min ) { if ( version_compare( PHP_VERSION, $min, '<' ) ) { Factory::getApplication()->enqueueMessage( 'You are currently using PHP ' . PHP_VERSION . ', ' . 'but Aimy IndexNow requires at least PHP ' . $min . '.', 'error' ); return false; } return true; } static private function check_joomla_version( $min ) { $jv = defined( 'JVERSION' ) ? JVERSION : 0; if ( version_compare( $jv, $min, '<' ) ) { Factory::getApplication()->enqueueMessage( 'You are currently using Joomla! ' . $jv . ', ' . 'but Aimy IndexNow requires at least Joomla! ' . $min . '.', 'error' ); return false; } return true; } static private function deleteExtensionParam( $name ) { $element = ( 'plg' == 'com' ? 'com_' : '' ) . 'aimyindexnow'; $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( 'params' ) ) ->from( $db->quoteName( '#__extensions' ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( $element ) ); $db->setQuery( $q ); $rv = $db->loadResult(); if ( empty( $rv ) ) { return false; } $params = new Registry(); $params->loadString( $rv ); if ( ! $params or ! $params->exists( $name ) ) { return false; } $params->remove( $name ); $q = $db->getQuery( true ); $q->update( $db->quoteName( '#__extensions' ) ) ->set( $db->quoteName( 'params' ) . ' = ' . $db->quote( $params->toString() ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( $element ) ); $db->setQuery( $q ); return $db->execute(); } } 
aimyindexnow.xml000064400000015113152354740050010007 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<extension version="3.0" type="plugin" group="content" method="upgrade">
    <name>Content - Aimy IndexNow (PRO)</name>
    <creationDate>2024-10-15</creationDate>
    <author>Aimy Extensions (Netzum Sorglos Software GmbH)</author>
    <authorEmail>info@aimy-extensions.com</authorEmail>
    <authorUrl>https://www.aimy-extensions.com/</authorUrl>
    <copyright>2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH</copyright>
    <license>GNU General Public License (GPL) v2</license>
    <version>6.0</version>
    <description>IndexNow support for your website (PRO)</description>
    <dlid prefix="dl_key=" suffix="" />
    <scriptfile>install-hints.php</scriptfile>
    <files>
        <filename plugin="aimyindexnow">aimyindexnow.php</filename>
        <filename>notifier.php</filename>
        <filename>info.php</filename>
        <folder>fields</folder>
        <folder>helpers</folder>
        <filename>sitemap.php</filename>
        <filename>index.html</filename>
    </files>
    <media destination="plg_aimyindexnow" folder="media">
        <filename>aimy-logo_340x327.png</filename>
        <filename>wait.gif</filename>
        <filename>keygen.js</filename>
        <filename>submit.js</filename>
        <filename>index.html</filename>
    </media>
    <languages>
        <language tag="en-GB">i18n/en-GB.plg_content_aimyindexnow.ini</language>
        <language tag="de-DE">i18n/de-DE.plg_content_aimyindexnow.ini</language>
        <language tag="es-ES">i18n/es-ES.plg_content_aimyindexnow.ini</language>
        <language tag="fa-IR">i18n/fa-IR.plg_content_aimyindexnow.ini</language>
        <language tag="prs-AF">i18n/prs-AF.plg_content_aimyindexnow.ini</language>
    </languages>
    <config>
      <fields name="params"
        addfieldpath="/plugins/content/aimyindexnow/fields/">
        <fieldset name="basic">
          <field name="key" type="indexnowkey" default=""
            class="inputbox"
            required="true"
            label="AIMY_IN_KEY_LBL"
            description="AIMY_IN_KEY_DSC" />
          <field name="min-submit-interval"
            type="integer"
            default="10"
            class="inputbox"
            label="AIMY_IN_MIN_SUBMIT_INTERVAL_LBL"
            description="AIMY_IN_MIN_SUBMIT_INTERVAL_DSC"
            first="10"
            last="60"
            step="5" />
          <field name="mode"
            type="radio" default="ask"
            class="btn-group"
            labelclass="control-group"
            label="AIMY_IN_MODE_LBL"
            description="AIMY_IN_MODE_DSC">
              <option value="ask">AIMY_IN_MODE_ASK</option>
              <option value="auto">AIMY_IN_MODE_AUTO</option>
              <option value="off">AIMY_IN_MODE_OFF</option>
          </field>
          <field name="disable-local"
            type="radio" default="1"
            class="btn-group btn-group-yesno"
            labelclass="control-group"
            label="AIMY_IN_DISABLE_LOCAL_LBL"
            description="AIMY_IN_DISABLE_LOCAL_DSC">
              <option value="1">JYES</option>
              <option value="0">JNO</option>
          </field>
          <field name="exclude-patterns"
            type="textarea"
            class="inputbox"
            rows="10"
            cols="30"
            default="*.gif&#13;&#10;*/sampledata/*&#13;&#10;*/cache/*&#13;&#10;*/thumbs/*&#13;&#10;*/component/*&#13;&#10;*/media/system/*&#13;&#10;*/assets/*&#13;&#10;*/checkout/*"
            label="AIMY_IN_EXCLUDE_PATTERNS_LBL"
            description="AIMY_IN_EXCLUDE_PATTERNS_DSC" />
          </fieldset>
          <fieldset name="content-support"
            label="AIMY_IN_CONTENT_SUPPORT_TAB_LBL"
            description="AIMY_IN_CONTENT_SUPPORT_TAB_DSC">
          <field name="support-com_content"
            type="radio" default="1"
            class="btn-group btn-group-yesno"
            labelclass="control-group"
            label="AIMY_IN_SUPPORT_COM_CONTENT_LBL">
              <option value="1">JYES</option>
              <option value="0">JNO</option>
          </field>
          <field name="support-com_categories"
            type="radio"
            default="0"
            class="btn-group btn-group-yesno aimy-pro-feature"
            labelclass="control-group"
            label="AIMY_IN_SUPPORT_COM_CATEGORIES_LBL">
              <option value="1">JYES</option>
              <option value="0">JNO</option>
          </field>
          <field name="support-com_media"
            type="radio"
            default="1"
            class="btn-group btn-group-yesno aimy-pro-feature"
            labelclass="control-group"
            label="AIMY_IN_SUPPORT_COM_MEDIA_LBL">
              <option value="1">JYES</option>
              <option value="0">JNO</option>
          </field>
          <field name="support-com_tags"
            type="radio"
            default="0"
            class="btn-group btn-group-yesno aimy-pro-feature"
            labelclass="control-group"
            label="AIMY_IN_SUPPORT_COM_TAGS_LBL">
              <option value="1">JYES</option>
              <option value="0">JNO</option>
          </field>
        </fieldset>
        <fieldset name="sitemap-support"
            label="AIMY_IN_SITEMAP_SUPPORT_TAB_LBL"
            description="AIMY_IN_SITEMAP_SUPPORT_TAB_DSC">
          <field name="pass-to-sitemap"
            type="radio"
            default="0"
            class="btn-group btn-group-yesno aimy-pro-feature"
            labelclass="control-group"
            label="AIMY_IN_PASS_TO_SITEMAP_LBL"
            description="AIMY_IN_PASS_TO_SITEMAP_DSC">
              <option value="1">JYES</option>
              <option value="0">JNO</option>
          </field>
          <field name="write-sitemap"
            type="radio"
            default="0"
            class="btn-group btn-group-yesno"
            labelclass="control-group"
            showon="pass-to-sitemap:1"
            label="AIMY_IN_WRITE_SITEMAP_LBL"
            description="AIMY_IN_WRITE_SITEMAP_DSC">
              <option value="1">JYES</option>
              <option value="0">JNO</option>
          </field>
        </fieldset>
        <fieldset name="key" label="AIMY_IN_KEY_TAB_LBL">
          <field name="dl_key" type="aimydownloadkey" default=""
            class="inputbox"
            required="false"
            filter="cmd"
            label="AIMY_IN_DL_KEY_LBL" />
        </fieldset>
      </fields>
    </config>
    <updateservers>
      <server
        type="extension"
        priority="1"
        name="Aimy IndexNow PRO Update Server">http://updates.aimy-extensions.com/joomla/plg_aimyindexnow-pro.xml</server>
    </updateservers>
</extension>
helpers/ComponentDataHelper.php000064400000002717152354740050012627 0ustar00<?php
/* Copyright (c) 2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          http://www.aimy-extensions.com/software-license.html
 */
 namespace Aimy\IndexNow\Helpers; defined( '_JEXEC' ) or die(); require_once( __DIR__ . '/PluginHelper.php' ); use Aimy\IndexNow\Helpers\PluginHelper; use Joomla\CMS\Table\Table; abstract class ComponentDataHelper { static public function get( $context, $primaryKey ) { $handler = sprintf( '%s::getData__%s', __CLASS__, PluginHelper::getCtxComponent( $context ) ); if ( ! is_callable( $handler ) ) { return false; } return $handler( PluginHelper::getCtxView( $context ), $primaryKey ); } static private function getData__com_content( $view, $primaryKey ) { if ( $view != 'article' ) { return false; } return self::getUsingJTable( 'Content', $primaryKey ); } static private function getData__com_categories( $view, $primaryKey ) { if ( $view != 'category' ) { return false; } return self::getUsingJTable( 'Category', $primaryKey ); } static private function getData__com_tags( $view, $primaryKey ) { if ( $view != 'tag' ) { return false; } return self::getUsingJTable( 'Tag', $primaryKey, 'TagsTable' ); } static private function getUsingJTable( $type, $primaryKey, $tablePrefix = 'JTable' ) { $t = Table::GetInstance( $type, $tablePrefix ); if ( $t && is_object( $t ) && $t->load( $primaryKey ) ) { return $t; } return false; } } 
helpers/ComponentInfoHelper.php000064400000011367152354740050012652 0ustar00<?php
/* Copyright (c) 2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          http://www.aimy-extensions.com/software-license.html
 */
 namespace Aimy\IndexNow\Helpers; defined( '_JEXEC' ) or die(); require_once( __DIR__ . '/PluginHelper.php' ); use Aimy\IndexNow\Helpers\PluginHelper; use Joomla\CMS\Factory; use Joomla\CMS\Router\Route; use Joomla\CMS\Uri\Uri; abstract class ComponentInfoHelper { static public function get( $context, &$data ) { $handler = sprintf( '%s::getInfo__%s', __CLASS__, PluginHelper::getCtxComponent( $context ) ); if ( ! is_callable( $handler ) ) { return false; } $ci = $handler( PluginHelper::getCtxView( $context ), $data ); if ( ! $ci or ( ! $ci->route && ! isset( $ci->path ) ) ) { if ( ! ( $ci && isset( $ci->ignore ) && $ci->ignore ) ) { Factory::getApplication()->enqueueMessage( $handler . ': No info retrieved' ); } return false; } if ( $ci->route ) { $ci->path = Route::link( 'site', 'index.php?' . $ci->route ); unset( $ci->route ); } $ci->url = PluginHelper::getAbsoluteUrl( $ci->path ); return $ci; } static private function getInfo__com_content( $view, &$data ) { if ( $view == 'article' or $view == 'form' ) { $ci = new \StdClass(); $ci->isPublished = ( $data->state == 1 ); $ci->isPublic = ( $data->access == 1 ); $ci->route = 'option=com_content&view=article&id=' . $data->id; $ci->robots = (new \JConfig())->robots; if ( isset( $data->alias ) && $data->alias ) { $ci->route .= ':' . $data->alias; } if ( isset( $data->catid ) && $data->catid ) { $ci->route .= '&catid=' . $data->catid; } if ( isset( $data->language ) ) { $ci->lang = $data->language; if ( $data->language != '*' ) { $ci->route .= '&lang=' . $data->language; } } if ( isset( $data->title ) && ! empty( $data->title ) ) { $ci->title = $data->title; } if ( isset( $data->metadata ) && ! empty( $data->metadata ) ) { $md = PluginHelper::jsonToObject( $data->metadata ); if ( $md && isset( $md->robots ) && ! empty( $md->robots ) ) { $ci->robots = $md->robots; } } $now = Factory::getDate()->format( 'Y-m-d H:i:s' ); if ( $data->publish_up > $now ) { $ci->isPublished = false; } if ( $now > $data->publish_down && ( $data->publish_down != '0000-00-00 00:00:00' && ! is_null( $data->publish_down ) ) ) { $ci->isPublished = false; } return $ci; } return false; } static private function getInfo__com_media( $view, &$data ) { if ( $view == 'file' ) { $ci = new \StdClass(); $path = false; if ( isset( $data->filepath ) ) { $path = $data->filepath; } elseif ( isset( $data->path ) && isset( $data->name ) ) { $path = JPATH_ROOT . '/' . PluginHelper::getComMediaImagePath() . $data->path . '/' . $data->name; $path = preg_replace( '#/{2,}#', '/', $path ); } if ( ! $path ) { return false; } $path = preg_replace( '#^\Q' . JPATH_ROOT . '\E/?#i', '', $path ); if ( ! $path ) { return false; } $ci->isPublished = true; $ci->isPublic = true; $ci->route = false; $ci->path = Uri::root( true ) . '/' . $path; $ci->title = basename( $path ); $ci->robots = false; return $ci; } elseif ( $view == 'folder' ) { $ci = new \StdClass(); $ci->ignore = true; return $ci; } return false; } static private function getInfo__com_tags( $view, &$data ) { if ( $view == 'tag' ) { $ci = new \StdClass(); $ci->isPublished = ( $data->published == 1 ); $ci->isPublic = ( $data->access == 1 ); $ci->route = sprintf( 'option=com_tags&view=tag&id=%d:%s', $data->id, $data->alias ); $ci->robots = (new \JConfig())->robots; if ( isset( $data->language ) ) { $ci->lang = $data->language; if ( $data->language != '*' ) { $ci->route .= '&lang=' . $data->language; } } if ( isset( $data->title ) && ! empty( $data->title ) ) { $ci->title = $data->title; } if ( isset( $data->metadata ) && ! empty( $data->metadata ) ) { $md = PluginHelper::jsonToObject( $data->metadata ); if ( $md && isset( $md->robots ) && ! empty( $md->robots ) ) { $ci->robots = $md->robots; } } return $ci; } return false; } static private function getInfo__com_categories( $view, &$data ) { if ( $view == 'category' ) { $ci = new \StdClass(); $ci->isPublished = ( $data->published == 1 ); $ci->isPublic = ( $data->access == 1 ); $ci->route = 'option=com_content&view=category&id=' . $data->id; $ci->robots = (new \JConfig())->robots; if ( isset( $data->alias ) && $data->alias ) { $ci->route .= ':' . $data->alias; } if ( isset( $data->language ) ) { $ci->lang = $data->language; if ( $data->language != '*' ) { $ci->route .= '&lang=' . $data->language; } } if ( isset( $data->title ) && ! empty( $data->title ) ) { $ci->title = $data->title; } if ( isset( $data->metadata ) && ! empty( $data->metadata ) ) { $md = PluginHelper::jsonToObject( $data->metadata ); if ( $md && isset( $md->robots ) && ! empty( $md->robots ) ) { $ci->robots = $md->robots; } } return $ci; } return false; } } 
helpers/DownloadKeyHelper.php000064400000014524152354740050012312 0ustar00<?php
/*
 * Copyright (c) 2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          http://www.aimy-extensions.com/software-license.html
 */
 namespace AimyIndexNow\Helpers; defined( '_JEXEC' ) or die(); use Joomla\CMS\Factory; use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Language\Text; use Joomla\CMS\HTML\HTMLHelper; use Joomla\Registry\Registry; abstract class DownloadKeyHelper { const V_KEY_MISSING = 0; const V_KEY_INVALID = 1; const V_KEY_DENIED = 2; const V_KEY_EXPIRED = 3; const V_KEY_GRANTED = 4; const V_KEY_FAILED = 5; static private $lastError = ''; static private $lastResponseData = array(); static private $serverBaseUrl = 'http://dl.aimy-extensions.com'; static public function getUpdatesiteId() { $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( 'update_site_id' ) ) ->from( $db->quoteName( '#__update_sites' ) ) ->where( $db->quoteName( 'name' ) . ' = ' . $db->quote( self::getUpdateServerName() ) ); $db->setQuery( $q ); return $db->loadResult(); } static public function getExtensionId() { $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( 'extension_id' ) ) ->from( $db->quoteName( '#__extensions' ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( self::getElementName() ) ); $db->setQuery( $q ); return $db->loadResult(); } static public function getEditLink() { if ( self::isJoomla3() ) { if ( 'plg' == 'com' ) { return 'index.php?option=com_config&view=component&' . 'component=com_aimyindexnow'; } $link = 'index.php?option=com_plugins'; if ( ! empty( $id = self::getExtensionId() ) ) { return $link . '&task=plugin.edit&extension_id=' . $id; } return $link . '&view=plugins'; } if ( $id = self::getUpdatesiteId() ) { return 'index.php?option=com_installer&' . 'task=updatesite.edit&update_site_id=' . $id; } return 'index.php?option=com_installer&view=updatesite'; } static public function passKeyToUpdatesites( $key ) { $id = self::getUpdateSiteId(); if ( ! $id ) { throw new \RuntimeException( 'Failed to determine update site id of AimyIndexNow' ); } $eqVal = ''; if ( ! empty( $key ) ) { $key = trim( $key ); if ( ! empty( $key ) ) { $eqVal = 'dl_key=' . $key; } } $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->update( $db->quoteName( '#__update_sites' ) ) ->set( $db->quoteName( 'extra_query' ) . ' = ' . $db->quote( $eqVal ) ) ->where( $db->quoteName( 'update_site_id' ) . ' = ' . $db->quote( $id ) ); $db->setQuery( $q ); return $db->execute(); } static public function getKey() { $key = self::getKeyFromUpdatesites(); if ( self::isJoomla3() && empty( $key ) ) { $key = self::getKeyFromParams(); } return $key; } static public function getKeyFromUpdatesites() { $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( 'extra_query' ) ) ->from( $db->quoteName( '#__update_sites' ) ) ->where( $db->quoteName( 'name' ) . ' = ' . $db->quote( self::getUpdateServerName() ) ); $db->setQuery( $q ); $rv = $db->loadResult(); if ( ! empty( $rv ) && preg_match( '#dl_key=(\S+)#', $rv, $m ) ) { return $m[ 1 ]; } return false; } static public function getKeyFromParams() { $params = self::getParams(); if ( $params->exists( 'dl_key' ) ) { return trim( $params->get( 'dl_key' ) ); } return false; } static public function validateKey( $key = false ) { if ( empty( $key ) ) { $key = self::getKey(); } $rv = new \StdClass(); $rv->state = self::sendValidationRequest( $key ); $rv->msg = false; $rv->data = self::$lastResponseData; $rv->valid = false; self::loadLanguageStrings(); switch ( $rv->state ) { case self::V_KEY_GRANTED: $rv->valid = true; break; case self::V_KEY_MISSING: $rv->msg = Text::sprintf( 'AIMY_IN_DL_KEY_MISSING', htmlspecialchars( self::getEditLink() ) ); break; case self::V_KEY_INVALID: $rv->msg = Text::sprintf( 'AIMY_IN_DL_KEY_INVALID', htmlspecialchars( self::getEditLink() ) ); break; case self::V_KEY_EXPIRED: $rv->msg = Text::sprintf( 'AIMY_IN_DL_KEY_EXPIRED', HtmlHelper::date( isset( $rv->data[ 'since' ] ) ? $rv->data[ 'since' ] : 'now', Text::_( 'DATE_FORMAT_FILTER_DATE' ) ), htmlspecialchars( 'https://www.aimy-extensions.com/joomla/indexnow.html' ) ); if ( isset( $rv->data[ 'code' ] ) ) { $rv->msg .= ' ' . Text::sprintf( 'AIMY_IN_DL_KEY_CODE', $rv->data[ 'code'] ); } break; case self::V_KEY_DENIED: $rv->msg = Text::sprintf( 'AIMY_IN_DL_KEY_DENIED', htmlspecialchars( 'https://www.aimy-extensions.com/joomla/indexnow.html' ) ); break; case self::V_KEY_FAILED: $rv->msg = Text::sprintf( 'AIMY_IN_DL_KEY_VALIDATION_FAILED', self::$lastError ); break; } return $rv; } static private function sendValidationRequest( $key ) { if ( empty( $key ) ) { return self::V_KEY_MISSING; } try { self::$lastError = self::$lastResponseData = ''; $resp = HttpFactory::getHttp()->get( self::$serverBaseUrl . '/check/key/plg_AimyIndexNow/' . $key ); if ( is_object( $resp ) ) { if ( $resp->code != 200 ) { self::$lastError = 'HTTP ' . $resp->code; return self::V_KEY_FAILED; } $json = json_decode( $resp->body, true ); if ( ! is_array( $json ) or ! isset( $json[ 'rv' ] ) ) { throw new \RuntimeException( 'Failed to parse JSON data' ); } self::$lastResponseData = $json; switch( $json[ 'rv' ] ) { case 'invalid key': return self::V_KEY_INVALID; case 'expired': return self::V_KEY_EXPIRED; case 'denied': return self::V_KEY_DENIED; case 'granted': return self::V_KEY_GRANTED; } } } catch ( \Exception $e ) { self::$lastError = $e->getMessage(); return self::V_KEY_FAILED; } return self::V_KEY_FAILED; } static private function getUpdateServerName() { return 'Aimy IndexNow PRO Update Server'; } static private function getElementName() { if ( 'plg' == 'com' ) { return 'com_aimyindexnow'; } return 'aimyindexnow'; } static private function loadLanguageStrings() { $n = 'plg_'; if ( ! empty( $jp = 'content' ) ) { $n .= $jp . '_'; } $n .= 'aimyindexnow'; Factory::getLanguage()->load( $n, JPATH_ADMINISTRATOR ); } static private function isJoomla3() { return ( strpos( JVERSION, '3.' ) === 0 ); } static public function getParams() { $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( 'params' ) ) ->from( $db->quoteName( '#__extensions' ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( self::getElementName() ) ); $db->setQuery( $q ); $rv = $db->loadResult(); if ( empty( $rv ) ) { return false; } $params = new Registry(); $params->loadString( $rv ); return $params; } } 
helpers/ExcludePatternHelper.php000064400000001422152354740050013012 0ustar00<?php
/*
 * Copyright (c) 2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          https://www.aimy-extensions.com/software-license.html
 */
 namespace Aimy\IndexNow\Helpers; defined( '_JEXEC' ) or die(); abstract class ExcludePatternHelper { static public function matches( $patterns, $url ) { foreach ( $patterns as $pattern ) { $pattern = trim( $pattern ); if ( self::match( $pattern, $url ) ) { return $pattern; } } return false; } static private function match( $pat, $s ) { $pps = explode( '*', $pat ); foreach ( $pps as $i => $p ) { $pps[ $i ] = preg_quote( $p, '/' ); } $re = '/^' . implode( '.*?', $pps ) . '$/'; return ( preg_match( $re, $s ) === 1 ); } } 
helpers/index.html000064400000000016152354740050010205 0ustar00<html></html>
helpers/PluginHelper.php000064400000011202152354740050011316 0ustar00<?php
/* Copyright (c) 2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          http://www.aimy-extensions.com/software-license.html
 */
 namespace Aimy\IndexNow\Helpers; defined( '_JEXEC' ) or die(); use Joomla\CMS\Factory; use Joomla\CMS\Uri\Uri; use Joomla\CMS\Filesystem\File; use Joomla\CMS\Language\Text; abstract class PluginHelper { static public function getElapsedMinutes( $stamp ) { return floor( ( time() - intval( $stamp ) ) / 60 ); } static public function getAbsoluteUrl( $relUrl ) { $u = Uri::getInstance( Uri::root() ); return sprintf( '%s://%s/%s', $u->getScheme(), $u->getHost(), ltrim( $relUrl, '/' ) ); } static public function getWebsiteIpAddress() { $host = Uri::getInstance( Uri::root() )->getHost(); $ip = gethostbyname( $host ); if ( $ip ) { return $ip; } $dns_6 = dns_get_record( $host, DNS_AAAA ); if ( $dns_6 && is_array( $dns_6 ) ) { foreach ( $dns_6 as $rec ) { if ( isset( $rec[ 'type' ] ) && $rec[ 'type' ] == 'AAAA' ) { return $rec[ 'ipv6' ]; } } } return false; } static public function getKeyfileName( $key ) { return $key . '.txt'; } static public function writeKeyfileIfNotExistent( $key ) { $path = rtrim( JPATH_ROOT, '/' ) . '/' . self::getKeyfileName( $key ); if ( file_exists( $path ) ) { return false; } if ( File::write( $path, "$key\n" ) ) { return true; } throw new \RuntimeException( $path . ': Failed to write keyfile' ); } static public function checkKey( $key ) { if ( empty( $key ) ) { throw new \RuntimeException( '<b>Aimy IndexNow</b>: ' . Text::sprintf( 'AIMY_IN_ERR_NO_KEY_SET_X', self::getPluginOptionsURL() ) ); } if ( strlen( $key ) < 8 or strlen( $key ) > 128 or ! preg_match( '/^[a-z0-9-]+$/i', $key ) or preg_match( '#^(robots|README|index|htaccess)$#', $key ) ) { throw new \RuntimeException( '<b>Aimy IndexNow</b>: ' . Text::sprintf( 'AIMY_IN_ERR_KEY_INVALID_X', self::getPluginOptionsURL() ) ); } } static public function isJoomla3() { return ( strpos( strVal( JVERSION ), '3.' ) === 0 ); } static public function inBackend() { if ( self::isJoomla3() ) { return Factory::getApplication()->isAdmin(); } return Factory::getApplication()->isClient( 'administrator' ); } static public function inFrontend() { if ( self::isJoomla3() ) { return Factory::getApplication()->isSite(); } return Factory::getApplication()->isClient( 'site' ); } static public function isFrontendEditing() { if ( self::inFrontend() && Factory::getConfig()->get( 'frontediting', false ) ) { $user = Factory::getUser(); return ( $user->guest != 1 ); } } static public function getCtxComponent( $context ) { $ctx = explode( '.', $context, 2 ); if ( ! is_array( $ctx ) or count( $ctx ) !== 2 ) { throw new \RuntimeException( 'Failed to parse context: ' . $context ); } return $ctx[ 0 ]; } static public function getCtxView( $context ) { $ctx = explode( '.', $context, 2 ); if ( ! is_array( $ctx ) or count( $ctx ) !== 2 ) { throw new \RuntimeException( 'Failed to parse context: ' . $context ); } return $ctx[ 1 ]; } static public function getPluginOptionsURL() { $id = false; try { $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( array( 'extension_id' ) ) ) ->from( $db->quoteName( '#__extensions' ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( 'aimyindexnow' ) ); $db->setQuery( $q ); $id = $db->loadResult(); } catch ( \Exception $e ) { } if ( $id ) { return 'index.php?option=com_plugins&amp;task=plugin.edit&amp;' . 'extension_id=' . $id; } return 'index.php?option=com_plugins&amp;view=plugins'; } static public function jsonToObject( $json ) { $obj = false; $flags = 0; if ( defined( 'JSON_THROW_ON_ERROR' ) ) { $flags += JSON_THROW_ON_ERROR; } try { $obj = \json_decode( $json, false, 512, $flags ); } catch ( \Exception $e ) { $obj = false; } return $obj; } static public function isLocalIpAddress( $ip ) { $v = filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ); return ($v === false); } static public function getComMediaImagePath() { if ( ! function_exists( 'json_decode' ) ) { return 'images'; } $params = false; try { $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( array( 'params' ) ) ) ->from( $db->quoteName( '#__extensions' ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( 'com_media' ) ); $db->setQuery( $q ); $params = $db->loadResult(); } catch ( \Exception $e ) { } if ( empty( $params ) or ! is_string( $params ) ) { return 'images'; } $params = json_decode( $params ); if ( empty( $params ) or ! isset( $params->image_path ) or empty( $params->image_path ) ) { return 'images'; } return trim( $params->image_path, '/ ' ); } } 
helpers/StorageHelper.php000064400000001327152354740050011473 0ustar00<?php
/* Copyright (c) 2022-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          http://www.aimy-extensions.com/software-license.html
 */
 namespace Aimy\IndexNow\Helpers; defined( '_JEXEC' ) or die(); use Joomla\CMS\Factory; abstract class StorageHelper { const NAMESPACE = 'AimyIndexNow'; static public function get( $k ) { return Factory::getSession()->get( self::encodeKey( $k ), false, self::NAMESPACE ); } static public function set( $k, $v ) { return Factory::getSession()->set( self::encodeKey( $k ), $v, self::NAMESPACE ); } static private function encodeKey( $k ) { return base64_encode( $k ); } } 
helpers/UpdateServer.php000064400000004715152354740050011344 0ustar00<?php
/*
 * Copyright (c) 2017-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 * Copyright (c) 2015-2017 Aimy Extensions, Lingua-Systems Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          http://www.aimy-extensions.com/software-license.html
 */
 defined( '_JEXEC' ) or die(); use Joomla\CMS\Factory; abstract class AimyIndexNowUpdateServer { static public function cleanup_server_list( &$adapter ) { $class = get_class( $adapter ); $element = 'aimyindexnow'; if ( strpos( $class, 'Component' ) ) { $element = 'com_' . $element; } elseif ( strpos( $class, 'Module' ) ) { $element = 'mod_' . $element; } $eid = self::get_extension_id( $element ); if ( empty( $eid ) ) { throw new RuntimeException( 'Could not determine element id' ); } return self::cleanup_servers( $eid, 'aimyindexnow.xml' ); } static private function cleanup_servers( $eid, $url_suffix ) { $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( 's.update_site_id' ) ) ->from( $db->quoteName( '#__update_sites_extensions', 'e' ) ) ->join( 'INNER', $db->quoteName( '#__update_sites', 's' ) . ' ON ' . $db->quoteName( 'e.update_site_id' ) . ' = ' . $db->quoteName( 's.update_site_id' ) ) ->where( $db->quoteName( 'e.extension_id' ) . ' = ' . $db->quote( $eid ) . ' AND ' . $db->quoteName( 's.location' ) . ' LIKE ' . $db->quote( '%' . $url_suffix ) ); $db->setQuery( $q ); $sites = $db->loadObjectList(); foreach ( $sites as $site ) { try { $db->transactionStart(); $q = $db->getQuery( true ); $q->delete( $db->quoteName( '#__update_sites' ) ) ->where( $db->quoteName( 'update_site_id' ) . ' = ' . $db->quote( $site->update_site_id ) ); $db->setQuery( $q ); $db->execute(); $q = $db->getQuery( true ); $q->delete( $db->quoteName( '#__update_sites_extensions' ) ) ->where( $db->quoteName( 'update_site_id' ) . ' = ' . $db->quote( $site->update_site_id ) ); $db->setQuery( $q ); $db->execute(); $db->transactionCommit(); } catch ( Exception $e ) { $db->transactionRollback(); throw new Exception( $e->getMessage() ); } } } static private function get_extension_id( $elem ) { $db = Factory::getDbo(); $q = $db->getQuery( true ); $q->select( $db->quoteName( 'extension_id' ) ) ->from( $db->quoteName( '#__extensions' ) ) ->where( $db->quoteName( 'element' ) . ' = ' . $db->quote( $elem ) ); $db->setQuery( $q ); $d = $db->loadObject(); if ( is_object( $d ) and isset( $d->extension_id ) ) { return $d->extension_id; } return null; } } 
fields/aimydownloadkey.php000064400000002370152354740050011732 0ustar00<?php
/*
 * Copyright (c) 2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          https://www.aimy-extensions.com/software-license.html
 */
 defined( '_JEXEC' ) or die(); require_once( __DIR__ . '/../helpers/DownloadKeyHelper.php' ); use Joomla\CMS\Form\FormField; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use AimyIndexNow\Helpers\DownloadKeyHelper; class JFormFieldAimyDownloadKey extends FormField { protected $type = 'aimydownloadkey'; protected $layout = 'joomla.form.field.text'; public function getInput() { if ( strpos( JVERSION, '3.' ) !== 0 ) { Factory::getDocument() ->addStyleDeclaration( '#fieldset-key .control-group { align-items: center; }' ); return '<div>' . Text::sprintf( 'AIMY_IN_DL_KEY_USE_DL_KEY_MANAGER', DownloadKeyHelper::getEditLink() ) . '</div>'; } Factory::getDocument() ->addStyleDeclaration( '#jform_params_dl_key,#jform_dl_key { min-width: 250px; }' ); return $this->getRenderer( $this->layout ) ->render( $this->getLayoutData() ); } protected function getLayoutData() { return array_merge( array( 'options' => array(), 'addonBefore' => '', 'addonAfter' => '', 'dirname' => '' ), parent::getLayoutData() ); } } 
fields/index.html000064400000000016152354740050010011 0ustar00<html></html>
fields/indexnowkey.php000064400000004307152354740050011100 0ustar00<?php
/*
 * Copyright (c) 2020-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          https://www.aimy-extensions.com/software-license.html
 */
 defined( '_JEXEC' ) or die(); require_once( __DIR__ . '/../helpers/PluginHelper.php' ); use Joomla\CMS\Form\FormField; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Uri\Uri; use Joomla\CMS\Language\Text; use Aimy\IndexNow\Helpers\PluginHelper; class JFormFieldIndexNowKey extends FormField { protected $type = 'indexnowkey'; protected $layout = 'joomla.form.field.text'; public function getInput() { HTMLHelper::_( 'jquery.framework' ); Factory::getDocument() ->addScript( Uri::root() . '/media/plg_aimyindexnow/keygen.js' ) ->addScriptDeclaration( 'jQuery(document).ready(function($)' . '{' . '$("<button></button>").text("' . Text::_( 'AIMY_IN_GENERATE_KEY' ) . '")' . '.addClass("btn btn-secondary btn-sm indexnowkeygen")' . '.click(' . 'function(e){' . '$("#' . $this->id . '").val(' . 'AimyIndexNowKeyGen(24)' . ');' . 'return e.preventDefault();' . '}).insertAfter($("#' . $this->id . '"));' . '});' ) ->addStyleDeclaration( PluginHelper::isJoomla3() ? '.indexnowkeygen{margin-left:12px}' : '.indexnowkeygen{margin-top:12px;}' ); return $this->getRenderer( $this->layout ) ->render( $this->getLayoutData() ); } public function getLabel() { if ( empty( $this->element[ 'label' ] ) ) { return ''; } $label = Text::_( $this->element[ 'label' ] ); $dsc = ''; $classes = array(); if ( ! empty( $this->class ) ) { $classes[] = $this->class; } if ( $this->required ) { $classes[] = 'required'; } if ( PluginHelper::isJoomla3() && isset( $this->element[ 'description' ] ) ) { $dsc = sprintf( ' data-content="%s" data-original-title="%s"', htmlspecialchars( Text::_( $this->element[ 'description' ] ) ), htmlspecialchars( $label ) ); $classes[] = 'hasPopover'; } return sprintf( '<label id="%s" class="%s"%s>%s</label>', $this->id . '-lbl', implode( ' ', $classes ), $dsc, $label ); } protected function getLayoutData() { return array_merge( array( 'options' => array(), 'addonBefore' => '', 'addonAfter' => '', 'dirname' => '' ), parent::getLayoutData(), ); } }