hermina/code_export.txt

15854 lines
634 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"./api/config.php" :
"""
<?php
// Zamenjajte z vašimi dejanskimi podatki!
define('SMTP_HOST', 'mail.herminamerc.si');
define('SMTP_USERNAME', 'info@herminamerc.si');
define('SMTP_PASSWORD', 'HERmina112358:'); // Bodite previdni s posebnimi znaki
define('SMTP_PORT', 465);
define('SMTP_SECURE', 'ssl'); // 'ssl' za port 465, 'tls' za 587
?>"""
"./api/phpmailer/src/DSNConfigurator.php" :
"""
<?php
/**
* PHPMailer - PHP email creation and transport class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2023 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
/**
* Configure PHPMailer with DSN string.
*
* @see https://en.wikipedia.org/wiki/Data_source_name
*
* @author Oleg Voronkovich <oleg-voronkovich@yandex.ru>
*/
class DSNConfigurator
{
/**
* Create new PHPMailer instance configured by DSN.
*
* @param string $dsn DSN
* @param bool $exceptions Should we throw external exceptions?
*
* @return PHPMailer
*/
public static function mailer($dsn, $exceptions = null)
{
static $configurator = null;
if (null === $configurator) {
$configurator = new DSNConfigurator();
}
return $configurator->configure(new PHPMailer($exceptions), $dsn);
}
/**
* Configure PHPMailer instance with DSN string.
*
* @param PHPMailer $mailer PHPMailer instance
* @param string $dsn DSN
*
* @return PHPMailer
*/
public function configure(PHPMailer $mailer, $dsn)
{
$config = $this->parseDSN($dsn);
$this->applyConfig($mailer, $config);
return $mailer;
}
/**
* Parse DSN string.
*
* @param string $dsn DSN
*
* @throws Exception If DSN is malformed
*
* @return array Configuration
*/
private function parseDSN($dsn)
{
$config = $this->parseUrl($dsn);
if (false === $config || !isset($config['scheme']) || !isset($config['host'])) {
throw new Exception('Malformed DSN');
}
if (isset($config['query'])) {
parse_str($config['query'], $config['query']);
}
return $config;
}
/**
* Apply configuration to mailer.
*
* @param PHPMailer $mailer PHPMailer instance
* @param array $config Configuration
*
* @throws Exception If scheme is invalid
*/
private function applyConfig(PHPMailer $mailer, $config)
{
switch ($config['scheme']) {
case 'mail':
$mailer->isMail();
break;
case 'sendmail':
$mailer->isSendmail();
break;
case 'qmail':
$mailer->isQmail();
break;
case 'smtp':
case 'smtps':
$mailer->isSMTP();
$this->configureSMTP($mailer, $config);
break;
default:
throw new Exception(
sprintf(
'Invalid scheme: "%s". Allowed values: "mail", "sendmail", "qmail", "smtp", "smtps".',
$config['scheme']
)
);
}
if (isset($config['query'])) {
$this->configureOptions($mailer, $config['query']);
}
}
/**
* Configure SMTP.
*
* @param PHPMailer $mailer PHPMailer instance
* @param array $config Configuration
*/
private function configureSMTP($mailer, $config)
{
$isSMTPS = 'smtps' === $config['scheme'];
if ($isSMTPS) {
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
}
$mailer->Host = $config['host'];
if (isset($config['port'])) {
$mailer->Port = $config['port'];
} elseif ($isSMTPS) {
$mailer->Port = SMTP::DEFAULT_SECURE_PORT;
}
$mailer->SMTPAuth = isset($config['user']) || isset($config['pass']);
if (isset($config['user'])) {
$mailer->Username = $config['user'];
}
if (isset($config['pass'])) {
$mailer->Password = $config['pass'];
}
}
/**
* Configure options.
*
* @param PHPMailer $mailer PHPMailer instance
* @param array $options Options
*
* @throws Exception If option is unknown
*/
private function configureOptions(PHPMailer $mailer, $options)
{
$allowedOptions = get_object_vars($mailer);
unset($allowedOptions['Mailer']);
unset($allowedOptions['SMTPAuth']);
unset($allowedOptions['Username']);
unset($allowedOptions['Password']);
unset($allowedOptions['Hostname']);
unset($allowedOptions['Port']);
unset($allowedOptions['ErrorInfo']);
$allowedOptions = \array_keys($allowedOptions);
foreach ($options as $key => $value) {
if (!in_array($key, $allowedOptions)) {
throw new Exception(
sprintf(
'Unknown option: "%s". Allowed values: "%s"',
$key,
implode('", "', $allowedOptions)
)
);
}
switch ($key) {
case 'AllowEmpty':
case 'SMTPAutoTLS':
case 'SMTPKeepAlive':
case 'SingleTo':
case 'UseSendmailOptions':
case 'do_verp':
case 'DKIM_copyHeaderFields':
$mailer->$key = (bool) $value;
break;
case 'Priority':
case 'SMTPDebug':
case 'WordWrap':
$mailer->$key = (int) $value;
break;
default:
$mailer->$key = $value;
break;
}
}
}
/**
* Parse a URL.
* Wrapper for the built-in parse_url function to work around a bug in PHP 5.5.
*
* @param string $url URL
*
* @return array|false
*/
protected function parseUrl($url)
{
if (\PHP_VERSION_ID >= 50600 || false === strpos($url, '?')) {
return parse_url($url);
}
$chunks = explode('?', $url);
if (is_array($chunks)) {
$result = parse_url($chunks[0]);
if (is_array($result)) {
$result['query'] = $chunks[1];
}
return $result;
}
return false;
}
}
"""
"./api/phpmailer/src/Exception.php" :
"""
<?php
/**
* PHPMailer Exception class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2020 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
/**
* PHPMailer exception handler.
*
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
*/
class Exception extends \Exception
{
/**
* Prettify error message output.
*
* @return string
*/
public function errorMessage()
{
return '<strong>' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "</strong><br />\n";
}
}
"""
"./api/phpmailer/src/OAuth.php" :
"""
<?php
/**
* PHPMailer - PHP email creation and transport class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2020 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
use League\OAuth2\Client\Grant\RefreshToken;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Token\AccessToken;
/**
* OAuth - OAuth2 authentication wrapper class.
* Uses the oauth2-client package from the League of Extraordinary Packages.
*
* @see https://oauth2-client.thephpleague.com
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
*/
class OAuth implements OAuthTokenProvider
{
/**
* An instance of the League OAuth Client Provider.
*
* @var AbstractProvider
*/
protected $provider;
/**
* The current OAuth access token.
*
* @var AccessToken
*/
protected $oauthToken;
/**
* The user's email address, usually used as the login ID
* and also the from address when sending email.
*
* @var string
*/
protected $oauthUserEmail = '';
/**
* The client secret, generated in the app definition of the service you're connecting to.
*
* @var string
*/
protected $oauthClientSecret = '';
/**
* The client ID, generated in the app definition of the service you're connecting to.
*
* @var string
*/
protected $oauthClientId = '';
/**
* The refresh token, used to obtain new AccessTokens.
*
* @var string
*/
protected $oauthRefreshToken = '';
/**
* OAuth constructor.
*
* @param array $options Associative array containing
* `provider`, `userName`, `clientSecret`, `clientId` and `refreshToken` elements
*/
public function __construct($options)
{
$this->provider = $options['provider'];
$this->oauthUserEmail = $options['userName'];
$this->oauthClientSecret = $options['clientSecret'];
$this->oauthClientId = $options['clientId'];
$this->oauthRefreshToken = $options['refreshToken'];
}
/**
* Get a new RefreshToken.
*
* @return RefreshToken
*/
protected function getGrant()
{
return new RefreshToken();
}
/**
* Get a new AccessToken.
*
* @return AccessToken
*/
protected function getToken()
{
return $this->provider->getAccessToken(
$this->getGrant(),
['refresh_token' => $this->oauthRefreshToken]
);
}
/**
* Generate a base64-encoded OAuth token.
*
* @return string
*/
public function getOauth64()
{
//Get a new token if it's not available or has expired
if (null === $this->oauthToken || $this->oauthToken->hasExpired()) {
$this->oauthToken = $this->getToken();
}
return base64_encode(
'user=' .
$this->oauthUserEmail .
"\001auth=Bearer " .
$this->oauthToken .
"\001\001"
);
}
}
"""
"./api/phpmailer/src/OAuthTokenProvider.php" :
"""
<?php
/**
* PHPMailer - PHP email creation and transport class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2020 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
/**
* OAuthTokenProvider - OAuth2 token provider interface.
* Provides base64 encoded OAuth2 auth strings for SMTP authentication.
*
* @see OAuth
* @see SMTP::authenticate()
*
* @author Peter Scopes (pdscopes)
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
*/
interface OAuthTokenProvider
{
/**
* Generate a base64-encoded OAuth token ensuring that the access token has not expired.
* The string to be base 64 encoded should be in the form:
* "user=<user_email_address>\001auth=Bearer <access_token>\001\001"
*
* @return string
*/
public function getOauth64();
}
"""
"./api/phpmailer/src/PHPMailer.php" :
"""
<?php
/**
* PHPMailer - PHP email creation and transport class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2020 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
/**
* PHPMailer - PHP email creation and transport class.
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
*/
class PHPMailer
{
const CHARSET_ASCII = 'us-ascii';
const CHARSET_ISO88591 = 'iso-8859-1';
const CHARSET_UTF8 = 'utf-8';
const CONTENT_TYPE_PLAINTEXT = 'text/plain';
const CONTENT_TYPE_TEXT_CALENDAR = 'text/calendar';
const CONTENT_TYPE_TEXT_HTML = 'text/html';
const CONTENT_TYPE_MULTIPART_ALTERNATIVE = 'multipart/alternative';
const CONTENT_TYPE_MULTIPART_MIXED = 'multipart/mixed';
const CONTENT_TYPE_MULTIPART_RELATED = 'multipart/related';
const ENCODING_7BIT = '7bit';
const ENCODING_8BIT = '8bit';
const ENCODING_BASE64 = 'base64';
const ENCODING_BINARY = 'binary';
const ENCODING_QUOTED_PRINTABLE = 'quoted-printable';
const ENCRYPTION_STARTTLS = 'tls';
const ENCRYPTION_SMTPS = 'ssl';
const ICAL_METHOD_REQUEST = 'REQUEST';
const ICAL_METHOD_PUBLISH = 'PUBLISH';
const ICAL_METHOD_REPLY = 'REPLY';
const ICAL_METHOD_ADD = 'ADD';
const ICAL_METHOD_CANCEL = 'CANCEL';
const ICAL_METHOD_REFRESH = 'REFRESH';
const ICAL_METHOD_COUNTER = 'COUNTER';
const ICAL_METHOD_DECLINECOUNTER = 'DECLINECOUNTER';
/**
* Email priority.
* Options: null (default), 1 = High, 3 = Normal, 5 = low.
* When null, the header is not set at all.
*
* @var int|null
*/
public $Priority;
/**
* The character set of the message.
*
* @var string
*/
public $CharSet = self::CHARSET_ISO88591;
/**
* The MIME Content-type of the message.
*
* @var string
*/
public $ContentType = self::CONTENT_TYPE_PLAINTEXT;
/**
* The message encoding.
* Options: "8bit", "7bit", "binary", "base64", and "quoted-printable".
*
* @var string
*/
public $Encoding = self::ENCODING_8BIT;
/**
* Holds the most recent mailer error message.
*
* @var string
*/
public $ErrorInfo = '';
/**
* The From email address for the message.
*
* @var string
*/
public $From = '';
/**
* The From name of the message.
*
* @var string
*/
public $FromName = '';
/**
* The envelope sender of the message.
* This will usually be turned into a Return-Path header by the receiver,
* and is the address that bounces will be sent to.
* If not empty, will be passed via `-f` to sendmail or as the 'MAIL FROM' value over SMTP.
*
* @var string
*/
public $Sender = '';
/**
* The Subject of the message.
*
* @var string
*/
public $Subject = '';
/**
* An HTML or plain text message body.
* If HTML then call isHTML(true).
*
* @var string
*/
public $Body = '';
/**
* The plain-text message body.
* This body can be read by mail clients that do not have HTML email
* capability such as mutt & Eudora.
* Clients that can read HTML will view the normal Body.
*
* @var string
*/
public $AltBody = '';
/**
* An iCal message part body.
* Only supported in simple alt or alt_inline message types
* To generate iCal event structures, use classes like EasyPeasyICS or iCalcreator.
*
* @see https://kigkonsult.se/iCalcreator/
*
* @var string
*/
public $Ical = '';
/**
* Value-array of "method" in Contenttype header "text/calendar"
*
* @var string[]
*/
protected static $IcalMethods = [
self::ICAL_METHOD_REQUEST,
self::ICAL_METHOD_PUBLISH,
self::ICAL_METHOD_REPLY,
self::ICAL_METHOD_ADD,
self::ICAL_METHOD_CANCEL,
self::ICAL_METHOD_REFRESH,
self::ICAL_METHOD_COUNTER,
self::ICAL_METHOD_DECLINECOUNTER,
];
/**
* The complete compiled MIME message body.
*
* @var string
*/
protected $MIMEBody = '';
/**
* The complete compiled MIME message headers.
*
* @var string
*/
protected $MIMEHeader = '';
/**
* Extra headers that createHeader() doesn't fold in.
*
* @var string
*/
protected $mailHeader = '';
/**
* Word-wrap the message body to this number of chars.
* Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance.
*
* @see static::STD_LINE_LENGTH
*
* @var int
*/
public $WordWrap = 0;
/**
* Which method to use to send mail.
* Options: "mail", "sendmail", or "smtp".
*
* @var string
*/
public $Mailer = 'mail';
/**
* The path to the sendmail program.
*
* @var string
*/
public $Sendmail = '/usr/sbin/sendmail';
/**
* Whether mail() uses a fully sendmail-compatible MTA.
* One which supports sendmail's "-oi -f" options.
*
* @var bool
*/
public $UseSendmailOptions = true;
/**
* The email address that a reading confirmation should be sent to, also known as read receipt.
*
* @var string
*/
public $ConfirmReadingTo = '';
/**
* The hostname to use in the Message-ID header and as default HELO string.
* If empty, PHPMailer attempts to find one with, in order,
* $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value
* 'localhost.localdomain'.
*
* @see PHPMailer::$Helo
*
* @var string
*/
public $Hostname = '';
/**
* An ID to be used in the Message-ID header.
* If empty, a unique id will be generated.
* You can set your own, but it must be in the format "<id@domain>",
* as defined in RFC5322 section 3.6.4 or it will be ignored.
*
* @see https://www.rfc-editor.org/rfc/rfc5322#section-3.6.4
*
* @var string
*/
public $MessageID = '';
/**
* The message Date to be used in the Date header.
* If empty, the current date will be added.
*
* @var string
*/
public $MessageDate = '';
/**
* SMTP hosts.
* Either a single hostname or multiple semicolon-delimited hostnames.
* You can also specify a different port
* for each host by using this format: [hostname:port]
* (e.g. "smtp1.example.com:25;smtp2.example.com").
* You can also specify encryption type, for example:
* (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465").
* Hosts will be tried in order.
*
* @var string
*/
public $Host = 'localhost';
/**
* The default SMTP server port.
*
* @var int
*/
public $Port = 25;
/**
* The SMTP HELO/EHLO name used for the SMTP connection.
* Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find
* one with the same method described above for $Hostname.
*
* @see PHPMailer::$Hostname
*
* @var string
*/
public $Helo = '';
/**
* What kind of encryption to use on the SMTP connection.
* Options: '', static::ENCRYPTION_STARTTLS, or static::ENCRYPTION_SMTPS.
*
* @var string
*/
public $SMTPSecure = '';
/**
* Whether to enable TLS encryption automatically if a server supports it,
* even if `SMTPSecure` is not set to 'tls'.
* Be aware that in PHP >= 5.6 this requires that the server's certificates are valid.
*
* @var bool
*/
public $SMTPAutoTLS = true;
/**
* Whether to use SMTP authentication.
* Uses the Username and Password properties.
*
* @see PHPMailer::$Username
* @see PHPMailer::$Password
*
* @var bool
*/
public $SMTPAuth = false;
/**
* Options array passed to stream_context_create when connecting via SMTP.
*
* @var array
*/
public $SMTPOptions = [];
/**
* SMTP username.
*
* @var string
*/
public $Username = '';
/**
* SMTP password.
*
* @var string
*/
public $Password = '';
/**
* SMTP authentication type. Options are CRAM-MD5, LOGIN, PLAIN, XOAUTH2.
* If not specified, the first one from that list that the server supports will be selected.
*
* @var string
*/
public $AuthType = '';
/**
* SMTP SMTPXClient command attributes
*
* @var array
*/
protected $SMTPXClient = [];
/**
* An implementation of the PHPMailer OAuthTokenProvider interface.
*
* @var OAuthTokenProvider
*/
protected $oauth;
/**
* The SMTP server timeout in seconds.
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2.
*
* @var int
*/
public $Timeout = 300;
/**
* Comma separated list of DSN notifications
* 'NEVER' under no circumstances a DSN must be returned to the sender.
* If you use NEVER all other notifications will be ignored.
* 'SUCCESS' will notify you when your mail has arrived at its destination.
* 'FAILURE' will arrive if an error occurred during delivery.
* 'DELAY' will notify you if there is an unusual delay in delivery, but the actual
* delivery's outcome (success or failure) is not yet decided.
*
* @see https://www.rfc-editor.org/rfc/rfc3461.html#section-4.1 for more information about NOTIFY
*/
public $dsn = '';
/**
* SMTP class debug output mode.
* Debug output level.
* Options:
* @see SMTP::DEBUG_OFF: No output
* @see SMTP::DEBUG_CLIENT: Client messages
* @see SMTP::DEBUG_SERVER: Client and server messages
* @see SMTP::DEBUG_CONNECTION: As SERVER plus connection status
* @see SMTP::DEBUG_LOWLEVEL: Noisy, low-level data output, rarely needed
*
* @see SMTP::$do_debug
*
* @var int
*/
public $SMTPDebug = 0;
/**
* How to handle debug output.
* Options:
* * `echo` Output plain-text as-is, appropriate for CLI
* * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
* * `error_log` Output to error log as configured in php.ini
* By default PHPMailer will use `echo` if run from a `cli` or `cli-server` SAPI, `html` otherwise.
* Alternatively, you can provide a callable expecting two params: a message string and the debug level:
*
* ```php
* $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
* ```
*
* Alternatively, you can pass in an instance of a PSR-3 compatible logger, though only `debug`
* level output is used:
*
* ```php
* $mail->Debugoutput = new myPsr3Logger;
* ```
*
* @see SMTP::$Debugoutput
*
* @var string|callable|\Psr\Log\LoggerInterface
*/
public $Debugoutput = 'echo';
/**
* Whether to keep the SMTP connection open after each message.
* If this is set to true then the connection will remain open after a send,
* and closing the connection will require an explicit call to smtpClose().
* It's a good idea to use this if you are sending multiple messages as it reduces overhead.
* See the mailing list example for how to use it.
*
* @var bool
*/
public $SMTPKeepAlive = false;
/**
* Whether to split multiple to addresses into multiple messages
* or send them all in one message.
* Only supported in `mail` and `sendmail` transports, not in SMTP.
*
* @var bool
*
* @deprecated 6.0.0 PHPMailer isn't a mailing list manager!
*/
public $SingleTo = false;
/**
* Storage for addresses when SingleTo is enabled.
*
* @var array
*/
protected $SingleToArray = [];
/**
* Whether to generate VERP addresses on send.
* Only applicable when sending via SMTP.
*
* @see https://en.wikipedia.org/wiki/Variable_envelope_return_path
* @see https://www.postfix.org/VERP_README.html Postfix VERP info
*
* @var bool
*/
public $do_verp = false;
/**
* Whether to allow sending messages with an empty body.
*
* @var bool
*/
public $AllowEmpty = false;
/**
* DKIM selector.
*
* @var string
*/
public $DKIM_selector = '';
/**
* DKIM Identity.
* Usually the email address used as the source of the email.
*
* @var string
*/
public $DKIM_identity = '';
/**
* DKIM passphrase.
* Used if your key is encrypted.
*
* @var string
*/
public $DKIM_passphrase = '';
/**
* DKIM signing domain name.
*
* @example 'example.com'
*
* @var string
*/
public $DKIM_domain = '';
/**
* DKIM Copy header field values for diagnostic use.
*
* @var bool
*/
public $DKIM_copyHeaderFields = true;
/**
* DKIM Extra signing headers.
*
* @example ['List-Unsubscribe', 'List-Help']
*
* @var array
*/
public $DKIM_extraHeaders = [];
/**
* DKIM private key file path.
*
* @var string
*/
public $DKIM_private = '';
/**
* DKIM private key string.
*
* If set, takes precedence over `$DKIM_private`.
*
* @var string
*/
public $DKIM_private_string = '';
/**
* Callback Action function name.
*
* The function that handles the result of the send email action.
* It is called out by send() for each email sent.
*
* Value can be any php callable: https://www.php.net/is_callable
*
* Parameters:
* bool $result result of the send action
* array $to email addresses of the recipients
* array $cc cc email addresses
* array $bcc bcc email addresses
* string $subject the subject
* string $body the email body
* string $from email address of sender
* string $extra extra information of possible use
* "smtp_transaction_id' => last smtp transaction id
*
* @var string
*/
public $action_function = '';
/**
* What to put in the X-Mailer header.
* Options: An empty string for PHPMailer default, whitespace/null for none, or a string to use.
*
* @var string|null
*/
public $XMailer = '';
/**
* Which validator to use by default when validating email addresses.
* May be a callable to inject your own validator, but there are several built-in validators.
* The default validator uses PHP's FILTER_VALIDATE_EMAIL filter_var option.
*
* If CharSet is UTF8, the validator is left at the default value,
* and you send to addresses that use non-ASCII local parts, then
* PHPMailer automatically changes to the 'eai' validator.
*
* @see PHPMailer::validateAddress()
*
* @var string|callable
*/
public static $validator = 'php';
/**
* An instance of the SMTP sender class.
*
* @var SMTP
*/
protected $smtp;
/**
* The array of 'to' names and addresses.
*
* @var array
*/
protected $to = [];
/**
* The array of 'cc' names and addresses.
*
* @var array
*/
protected $cc = [];
/**
* The array of 'bcc' names and addresses.
*
* @var array
*/
protected $bcc = [];
/**
* The array of reply-to names and addresses.
*
* @var array
*/
protected $ReplyTo = [];
/**
* An array of all kinds of addresses.
* Includes all of $to, $cc, $bcc.
*
* @see PHPMailer::$to
* @see PHPMailer::$cc
* @see PHPMailer::$bcc
*
* @var array
*/
protected $all_recipients = [];
/**
* An array of names and addresses queued for validation.
* In send(), valid and non duplicate entries are moved to $all_recipients
* and one of $to, $cc, or $bcc.
* This array is used only for addresses with IDN.
*
* @see PHPMailer::$to
* @see PHPMailer::$cc
* @see PHPMailer::$bcc
* @see PHPMailer::$all_recipients
*
* @var array
*/
protected $RecipientsQueue = [];
/**
* An array of reply-to names and addresses queued for validation.
* In send(), valid and non duplicate entries are moved to $ReplyTo.
* This array is used only for addresses with IDN.
*
* @see PHPMailer::$ReplyTo
*
* @var array
*/
protected $ReplyToQueue = [];
/**
* Whether the need for SMTPUTF8 has been detected. Set by
* preSend() if necessary.
*
* @var bool
*/
public $UseSMTPUTF8 = false;
/**
* The array of attachments.
*
* @var array
*/
protected $attachment = [];
/**
* The array of custom headers.
*
* @var array
*/
protected $CustomHeader = [];
/**
* The most recent Message-ID (including angular brackets).
*
* @var string
*/
protected $lastMessageID = '';
/**
* The message's MIME type.
*
* @var string
*/
protected $message_type = '';
/**
* The array of MIME boundary strings.
*
* @var array
*/
protected $boundary = [];
/**
* The array of available text strings for the current language.
*
* @var array
*/
protected $language = [];
/**
* The number of errors encountered.
*
* @var int
*/
protected $error_count = 0;
/**
* The S/MIME certificate file path.
*
* @var string
*/
protected $sign_cert_file = '';
/**
* The S/MIME key file path.
*
* @var string
*/
protected $sign_key_file = '';
/**
* The optional S/MIME extra certificates ("CA Chain") file path.
*
* @var string
*/
protected $sign_extracerts_file = '';
/**
* The S/MIME password for the key.
* Used only if the key is encrypted.
*
* @var string
*/
protected $sign_key_pass = '';
/**
* Whether to throw exceptions for errors.
*
* @var bool
*/
protected $exceptions = false;
/**
* Unique ID used for message ID and boundaries.
*
* @var string
*/
protected $uniqueid = '';
/**
* The PHPMailer Version number.
*
* @var string
*/
const VERSION = '6.10.0';
/**
* Error severity: message only, continue processing.
*
* @var int
*/
const STOP_MESSAGE = 0;
/**
* Error severity: message, likely ok to continue processing.
*
* @var int
*/
const STOP_CONTINUE = 1;
/**
* Error severity: message, plus full stop, critical error reached.
*
* @var int
*/
const STOP_CRITICAL = 2;
/**
* The SMTP standard CRLF line break.
* If you want to change line break format, change static::$LE, not this.
*/
const CRLF = "\r\n";
/**
* "Folding White Space" a white space string used for line folding.
*/
const FWS = ' ';
/**
* SMTP RFC standard line ending; Carriage Return, Line Feed.
*
* @var string
*/
protected static $LE = self::CRLF;
/**
* The maximum line length supported by mail().
*
* Background: mail() will sometimes corrupt messages
* with headers longer than 65 chars, see #818.
*
* @var int
*/
const MAIL_MAX_LINE_LENGTH = 63;
/**
* The maximum line length allowed by RFC 2822 section 2.1.1.
*
* @var int
*/
const MAX_LINE_LENGTH = 998;
/**
* The lower maximum line length allowed by RFC 2822 section 2.1.1.
* This length does NOT include the line break
* 76 means that lines will be 77 or 78 chars depending on whether
* the line break format is LF or CRLF; both are valid.
*
* @var int
*/
const STD_LINE_LENGTH = 76;
/**
* Constructor.
*
* @param bool $exceptions Should we throw external exceptions?
*/
public function __construct($exceptions = null)
{
if (null !== $exceptions) {
$this->exceptions = (bool) $exceptions;
}
//Pick an appropriate debug output format automatically
$this->Debugoutput = (strpos(PHP_SAPI, 'cli') !== false ? 'echo' : 'html');
}
/**
* Destructor.
*/
public function __destruct()
{
//Close any open SMTP connection nicely
$this->smtpClose();
}
/**
* Call mail() in a safe_mode-aware fashion.
* Also, unless sendmail_path points to sendmail (or something that
* claims to be sendmail), don't pass params (not a perfect fix,
* but it will do).
*
* @param string $to To
* @param string $subject Subject
* @param string $body Message Body
* @param string $header Additional Header(s)
* @param string|null $params Params
*
* @return bool
*/
private function mailPassthru($to, $subject, $body, $header, $params)
{
//Check overloading of mail function to avoid double-encoding
if ((int)ini_get('mbstring.func_overload') & 1) {
$subject = $this->secureHeader($subject);
} else {
$subject = $this->encodeHeader($this->secureHeader($subject));
}
//Calling mail() with null params breaks
$this->edebug('Sending with mail()');
$this->edebug('Sendmail path: ' . ini_get('sendmail_path'));
$this->edebug("Envelope sender: {$this->Sender}");
$this->edebug("To: {$to}");
$this->edebug("Subject: {$subject}");
$this->edebug("Headers: {$header}");
if (!$this->UseSendmailOptions || null === $params) {
$result = @mail($to, $subject, $body, $header);
} else {
$this->edebug("Additional params: {$params}");
$result = @mail($to, $subject, $body, $header, $params);
}
$this->edebug('Result: ' . ($result ? 'true' : 'false'));
return $result;
}
/**
* Output debugging info via a user-defined method.
* Only generates output if debug output is enabled.
*
* @see PHPMailer::$Debugoutput
* @see PHPMailer::$SMTPDebug
*
* @param string $str
*/
protected function edebug($str)
{
if ($this->SMTPDebug <= 0) {
return;
}
//Is this a PSR-3 logger?
if ($this->Debugoutput instanceof \Psr\Log\LoggerInterface) {
$this->Debugoutput->debug(rtrim($str, "\r\n"));
return;
}
//Avoid clash with built-in function names
if (is_callable($this->Debugoutput) && !in_array($this->Debugoutput, ['error_log', 'html', 'echo'])) {
call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
return;
}
switch ($this->Debugoutput) {
case 'error_log':
//Don't output, just log
/** @noinspection ForgottenDebugOutputInspection */
error_log($str);
break;
case 'html':
//Cleans up output a bit for a better looking, HTML-safe output
echo htmlentities(
preg_replace('/[\r\n]+/', '', $str),
ENT_QUOTES,
'UTF-8'
), "<br>\n";
break;
case 'echo':
default:
//Normalize line breaks
$str = preg_replace('/\r\n|\r/m', "\n", $str);
echo gmdate('Y-m-d H:i:s'),
"\t",
//Trim trailing space
trim(
//Indent for readability, except for trailing break
str_replace(
"\n",
"\n \t ",
trim($str)
)
),
"\n";
}
}
/**
* Sets message type to HTML or plain.
*
* @param bool $isHtml True for HTML mode
*/
public function isHTML($isHtml = true)
{
if ($isHtml) {
$this->ContentType = static::CONTENT_TYPE_TEXT_HTML;
} else {
$this->ContentType = static::CONTENT_TYPE_PLAINTEXT;
}
}
/**
* Send messages using SMTP.
*/
public function isSMTP()
{
$this->Mailer = 'smtp';
}
/**
* Send messages using PHP's mail() function.
*/
public function isMail()
{
$this->Mailer = 'mail';
}
/**
* Send messages using $Sendmail.
*/
public function isSendmail()
{
$ini_sendmail_path = ini_get('sendmail_path');
if (false === stripos($ini_sendmail_path, 'sendmail')) {
$this->Sendmail = '/usr/sbin/sendmail';
} else {
$this->Sendmail = $ini_sendmail_path;
}
$this->Mailer = 'sendmail';
}
/**
* Send messages using qmail.
*/
public function isQmail()
{
$ini_sendmail_path = ini_get('sendmail_path');
if (false === stripos($ini_sendmail_path, 'qmail')) {
$this->Sendmail = '/var/qmail/bin/qmail-inject';
} else {
$this->Sendmail = $ini_sendmail_path;
}
$this->Mailer = 'qmail';
}
/**
* Add a "To" address.
*
* @param string $address The email address to send to
* @param string $name
*
* @throws Exception
*
* @return bool true on success, false if address already used or invalid in some way
*/
public function addAddress($address, $name = '')
{
return $this->addOrEnqueueAnAddress('to', $address, $name);
}
/**
* Add a "CC" address.
*
* @param string $address The email address to send to
* @param string $name
*
* @throws Exception
*
* @return bool true on success, false if address already used or invalid in some way
*/
public function addCC($address, $name = '')
{
return $this->addOrEnqueueAnAddress('cc', $address, $name);
}
/**
* Add a "BCC" address.
*
* @param string $address The email address to send to
* @param string $name
*
* @throws Exception
*
* @return bool true on success, false if address already used or invalid in some way
*/
public function addBCC($address, $name = '')
{
return $this->addOrEnqueueAnAddress('bcc', $address, $name);
}
/**
* Add a "Reply-To" address.
*
* @param string $address The email address to reply to
* @param string $name
*
* @throws Exception
*
* @return bool true on success, false if address already used or invalid in some way
*/
public function addReplyTo($address, $name = '')
{
return $this->addOrEnqueueAnAddress('Reply-To', $address, $name);
}
/**
* Add an address to one of the recipient arrays or to the ReplyTo array. Because PHPMailer
* can't validate addresses with an IDN without knowing the PHPMailer::$CharSet (that can still
* be modified after calling this function), addition of such addresses is delayed until send().
* Addresses that have been added already return false, but do not throw exceptions.
*
* @param string $kind One of 'to', 'cc', 'bcc', or 'Reply-To'
* @param string $address The email address
* @param string $name An optional username associated with the address
*
* @throws Exception
*
* @return bool true on success, false if address already used or invalid in some way
*/
protected function addOrEnqueueAnAddress($kind, $address, $name)
{
$pos = false;
if ($address !== null) {
$address = trim($address);
$pos = strrpos($address, '@');
}
if (false === $pos) {
//At-sign is missing.
$error_message = sprintf(
'%s (%s): %s',
$this->lang('invalid_address'),
$kind,
$address
);
$this->setError($error_message);
$this->edebug($error_message);
if ($this->exceptions) {
throw new Exception($error_message);
}
return false;
}
if ($name !== null && is_string($name)) {
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
} else {
$name = '';
}
$params = [$kind, $address, $name];
//Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
//Domain is assumed to be whatever is after the last @ symbol in the address
if ($this->has8bitChars(substr($address, ++$pos))) {
if (static::idnSupported()) {
if ('Reply-To' !== $kind) {
if (!array_key_exists($address, $this->RecipientsQueue)) {
$this->RecipientsQueue[$address] = $params;
return true;
}
} elseif (!array_key_exists($address, $this->ReplyToQueue)) {
$this->ReplyToQueue[$address] = $params;
return true;
}
}
//We have an 8-bit domain, but we are missing the necessary extensions to support it
//Or we are already sending to this address
return false;
}
//Immediately add standard addresses without IDN.
return call_user_func_array([$this, 'addAnAddress'], $params);
}
/**
* Set the boundaries to use for delimiting MIME parts.
* If you override this, ensure you set all 3 boundaries to unique values.
* The default boundaries include a "=_" sequence which cannot occur in quoted-printable bodies,
* as suggested by https://www.rfc-editor.org/rfc/rfc2045#section-6.7
*
* @return void
*/
public function setBoundaries()
{
$this->uniqueid = $this->generateId();
$this->boundary[1] = 'b1=_' . $this->uniqueid;
$this->boundary[2] = 'b2=_' . $this->uniqueid;
$this->boundary[3] = 'b3=_' . $this->uniqueid;
}
/**
* Add an address to one of the recipient arrays or to the ReplyTo array.
* Addresses that have been added already return false, but do not throw exceptions.
*
* @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
* @param string $address The email address to send, resp. to reply to
* @param string $name
*
* @throws Exception
*
* @return bool true on success, false if address already used or invalid in some way
*/
protected function addAnAddress($kind, $address, $name = '')
{
if (
self::$validator === 'php' &&
((bool) preg_match('/[\x80-\xFF]/', $address))
) {
//The caller has not altered the validator and is sending to an address
//with UTF-8, so assume that they want UTF-8 support instead of failing
$this->CharSet = self::CHARSET_UTF8;
self::$validator = 'eai';
}
if (!in_array($kind, ['to', 'cc', 'bcc', 'Reply-To'])) {
$error_message = sprintf(
'%s: %s',
$this->lang('Invalid recipient kind'),
$kind
);
$this->setError($error_message);
$this->edebug($error_message);
if ($this->exceptions) {
throw new Exception($error_message);
}
return false;
}
if (!static::validateAddress($address)) {
$error_message = sprintf(
'%s (%s): %s',
$this->lang('invalid_address'),
$kind,
$address
);
$this->setError($error_message);
$this->edebug($error_message);
if ($this->exceptions) {
throw new Exception($error_message);
}
return false;
}
if ('Reply-To' !== $kind) {
if (!array_key_exists(strtolower($address), $this->all_recipients)) {
$this->{$kind}[] = [$address, $name];
$this->all_recipients[strtolower($address)] = true;
return true;
}
} elseif (!array_key_exists(strtolower($address), $this->ReplyTo)) {
$this->ReplyTo[strtolower($address)] = [$address, $name];
return true;
}
return false;
}
/**
* Parse and validate a string containing one or more RFC822-style comma-separated email addresses
* of the form "display name <address>" into an array of name/address pairs.
* Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available.
* Note that quotes in the name part are removed.
*
* @see https://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
*
* @param string $addrstr The address list string
* @param bool $useimap Whether to use the IMAP extension to parse the list
* @param string $charset The charset to use when decoding the address list string.
*
* @return array
*/
public static function parseAddresses($addrstr, $useimap = true, $charset = self::CHARSET_ISO88591)
{
$addresses = [];
if ($useimap && function_exists('imap_rfc822_parse_adrlist')) {
//Use this built-in parser if it's available
$list = imap_rfc822_parse_adrlist($addrstr, '');
// Clear any potential IMAP errors to get rid of notices being thrown at end of script.
imap_errors();
foreach ($list as $address) {
if (
'.SYNTAX-ERROR.' !== $address->host &&
static::validateAddress($address->mailbox . '@' . $address->host)
) {
//Decode the name part if it's present and encoded
if (
property_exists($address, 'personal') &&
//Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
defined('MB_CASE_UPPER') &&
preg_match('/^=\?.*\?=$/s', $address->personal)
) {
$origCharset = mb_internal_encoding();
mb_internal_encoding($charset);
//Undo any RFC2047-encoded spaces-as-underscores
$address->personal = str_replace('_', '=20', $address->personal);
//Decode the name
$address->personal = mb_decode_mimeheader($address->personal);
mb_internal_encoding($origCharset);
}
$addresses[] = [
'name' => (property_exists($address, 'personal') ? $address->personal : ''),
'address' => $address->mailbox . '@' . $address->host,
];
}
}
} else {
//Use this simpler parser
$list = explode(',', $addrstr);
foreach ($list as $address) {
$address = trim($address);
//Is there a separate name part?
if (strpos($address, '<') === false) {
//No separate name, just use the whole thing
if (static::validateAddress($address)) {
$addresses[] = [
'name' => '',
'address' => $address,
];
}
} else {
list($name, $email) = explode('<', $address);
$email = trim(str_replace('>', '', $email));
$name = trim($name);
if (static::validateAddress($email)) {
//Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
//If this name is encoded, decode it
if (defined('MB_CASE_UPPER') && preg_match('/^=\?.*\?=$/s', $name)) {
$origCharset = mb_internal_encoding();
mb_internal_encoding($charset);
//Undo any RFC2047-encoded spaces-as-underscores
$name = str_replace('_', '=20', $name);
//Decode the name
$name = mb_decode_mimeheader($name);
mb_internal_encoding($origCharset);
}
$addresses[] = [
//Remove any surrounding quotes and spaces from the name
'name' => trim($name, '\'" '),
'address' => $email,
];
}
}
}
}
return $addresses;
}
/**
* Set the From and FromName properties.
*
* @param string $address
* @param string $name
* @param bool $auto Whether to also set the Sender address, defaults to true
*
* @throws Exception
*
* @return bool
*/
public function setFrom($address, $name = '', $auto = true)
{
$address = trim((string)$address);
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
//Don't validate now addresses with IDN. Will be done in send().
$pos = strrpos($address, '@');
if (
(false === $pos)
|| ((!$this->has8bitChars(substr($address, ++$pos)) || !static::idnSupported())
&& !static::validateAddress($address))
) {
$error_message = sprintf(
'%s (From): %s',
$this->lang('invalid_address'),
$address
);
$this->setError($error_message);
$this->edebug($error_message);
if ($this->exceptions) {
throw new Exception($error_message);
}
return false;
}
$this->From = $address;
$this->FromName = $name;
if ($auto && empty($this->Sender)) {
$this->Sender = $address;
}
return true;
}
/**
* Return the Message-ID header of the last email.
* Technically this is the value from the last time the headers were created,
* but it's also the message ID of the last sent message except in
* pathological cases.
*
* @return string
*/
public function getLastMessageID()
{
return $this->lastMessageID;
}
/**
* Check that a string looks like an email address.
* Validation patterns supported:
* * `auto` Pick best pattern automatically;
* * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0;
* * `pcre` Use old PCRE implementation;
* * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
* * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
* * `eai` Use a pattern similar to the HTML5 spec for 'email' and to firefox, extended to support EAI (RFC6530).
* * `noregex` Don't use a regex: super fast, really dumb.
* Alternatively you may pass in a callable to inject your own validator, for example:
*
* ```php
* PHPMailer::validateAddress('user@example.com', function($address) {
* return (strpos($address, '@') !== false);
* });
* ```
*
* You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
*
* @param string $address The email address to check
* @param string|callable $patternselect Which pattern to use
*
* @return bool
*/
public static function validateAddress($address, $patternselect = null)
{
if (null === $patternselect) {
$patternselect = static::$validator;
}
//Don't allow strings as callables, see SECURITY.md and CVE-2021-3603
if (is_callable($patternselect) && !is_string($patternselect)) {
return call_user_func($patternselect, $address);
}
//Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
if (strpos($address, "\n") !== false || strpos($address, "\r") !== false) {
return false;
}
switch ($patternselect) {
case 'pcre': //Kept for BC
case 'pcre8':
/*
* A more complex and more permissive version of the RFC5322 regex on which FILTER_VALIDATE_EMAIL
* is based.
* In addition to the addresses allowed by filter_var, also permits:
* * dotless domains: `a@b`
* * comments: `1234 @ local(blah) .machine .example`
* * quoted elements: `'"test blah"@example.org'`
* * numeric TLDs: `a@b.123`
* * unbracketed IPv4 literals: `a@192.168.0.1`
* * IPv6 literals: 'first.last@[IPv6:a1::]'
* Not all of these will necessarily work for sending!
*
* @copyright 2009-2010 Michael Rushton
* Feel free to use and redistribute this code. But please keep this copyright notice.
*/
return (bool) preg_match(
'/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
'((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
'(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
'([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
'(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
'(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
'|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
'|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
'|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
$address
);
case 'html5':
/*
* This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
*
* @see https://html.spec.whatwg.org/#e-mail-state-(type=email)
*/
return (bool) preg_match(
'/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
'[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
$address
);
case 'eai':
/*
* This is the pattern used in the HTML5 spec for validation of 'email' type
* form input elements (as above), modified to accept Unicode email addresses.
* This is also more lenient than Firefox' html5 spec, in order to make the regex faster.
* 'eai' is an acronym for Email Address Internationalization.
* This validator is selected automatically if you attempt to use recipient addresses
* that contain Unicode characters in the local part.
*
* @see https://html.spec.whatwg.org/#e-mail-state-(type=email)
* @see https://en.wikipedia.org/wiki/International_email
*/
return (bool) preg_match(
'/^[-\p{L}\p{N}\p{M}.!#$%&\'*+\/=?^_`{|}~]+@[\p{L}\p{N}\p{M}](?:[\p{L}\p{N}\p{M}-]{0,61}' .
'[\p{L}\p{N}\p{M}])?(?:\.[\p{L}\p{N}\p{M}]' .
'(?:[-\p{L}\p{N}\p{M}]{0,61}[\p{L}\p{N}\p{M}])?)*$/usD',
$address
);
case 'php':
default:
return filter_var($address, FILTER_VALIDATE_EMAIL) !== false;
}
}
/**
* Tells whether IDNs (Internationalized Domain Names) are supported or not. This requires the
* `intl` and `mbstring` PHP extensions.
*
* @return bool `true` if required functions for IDN support are present
*/
public static function idnSupported()
{
return function_exists('idn_to_ascii') && function_exists('mb_convert_encoding');
}
/**
* Converts IDN in given email address to its ASCII form, also known as punycode, if possible.
* Important: Address must be passed in same encoding as currently set in PHPMailer::$CharSet.
* This function silently returns unmodified address if:
* - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form)
* - Conversion to punycode is impossible (e.g. required PHP functions are not available)
* or fails for any reason (e.g. domain contains characters not allowed in an IDN).
*
* @see PHPMailer::$CharSet
*
* @param string $address The email address to convert
*
* @return string The encoded address in ASCII form
*/
public function punyencodeAddress($address)
{
//Verify we have required functions, CharSet, and at-sign.
$pos = strrpos($address, '@');
if (
!empty($this->CharSet) &&
false !== $pos &&
static::idnSupported()
) {
$domain = substr($address, ++$pos);
//Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
if ($this->has8bitChars($domain) && @mb_check_encoding($domain, $this->CharSet)) {
//Convert the domain from whatever charset it's in to UTF-8
$domain = mb_convert_encoding($domain, self::CHARSET_UTF8, $this->CharSet);
//Ignore IDE complaints about this line - method signature changed in PHP 5.4
$errorcode = 0;
if (defined('INTL_IDNA_VARIANT_UTS46')) {
//Use the current punycode standard (appeared in PHP 7.2)
$punycode = idn_to_ascii(
$domain,
\IDNA_DEFAULT | \IDNA_USE_STD3_RULES | \IDNA_CHECK_BIDI |
\IDNA_CHECK_CONTEXTJ | \IDNA_NONTRANSITIONAL_TO_ASCII,
\INTL_IDNA_VARIANT_UTS46
);
} elseif (defined('INTL_IDNA_VARIANT_2003')) {
//Fall back to this old, deprecated/removed encoding
$punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VARIANT_2003);
} else {
//Fall back to a default we don't know about
$punycode = idn_to_ascii($domain, $errorcode);
}
if (false !== $punycode) {
return substr($address, 0, $pos) . $punycode;
}
}
}
return $address;
}
/**
* Create a message and send it.
* Uses the sending method specified by $Mailer.
*
* @throws Exception
*
* @return bool false on error - See the ErrorInfo property for details of the error
*/
public function send()
{
try {
if (!$this->preSend()) {
return false;
}
return $this->postSend();
} catch (Exception $exc) {
$this->mailHeader = '';
$this->setError($exc->getMessage());
if ($this->exceptions) {
throw $exc;
}
return false;
}
}
/**
* Prepare a message for sending.
*
* @throws Exception
*
* @return bool
*/
public function preSend()
{
if (
'smtp' === $this->Mailer
|| ('mail' === $this->Mailer && (\PHP_VERSION_ID >= 80000 || stripos(PHP_OS, 'WIN') === 0))
) {
//SMTP mandates RFC-compliant line endings
//and it's also used with mail() on Windows
static::setLE(self::CRLF);
} else {
//Maintain backward compatibility with legacy Linux command line mailers
static::setLE(PHP_EOL);
}
//Check for buggy PHP versions that add a header with an incorrect line break
if (
'mail' === $this->Mailer
&& ((\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70017)
|| (\PHP_VERSION_ID >= 70100 && \PHP_VERSION_ID < 70103))
&& ini_get('mail.add_x_header') === '1'
&& stripos(PHP_OS, 'WIN') === 0
) {
trigger_error($this->lang('buggy_php'), E_USER_WARNING);
}
try {
$this->error_count = 0; //Reset errors
$this->mailHeader = '';
//The code below tries to support full use of Unicode,
//while remaining compatible with legacy SMTP servers to
//the greatest degree possible: If the message uses
//Unicode in the local parts of any addresses, it is sent
//using SMTPUTF8. If not, it it sent using
//punycode-encoded domains and plain SMTP.
if (
static::CHARSET_UTF8 === strtolower($this->CharSet) &&
($this->anyAddressHasUnicodeLocalPart($this->RecipientsQueue) ||
$this->anyAddressHasUnicodeLocalPart(array_keys($this->all_recipients)) ||
$this->anyAddressHasUnicodeLocalPart($this->ReplyToQueue) ||
$this->addressHasUnicodeLocalPart($this->From))
) {
$this->UseSMTPUTF8 = true;
}
//Dequeue recipient and Reply-To addresses with IDN
foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
if (!$this->UseSMTPUTF8) {
$params[1] = $this->punyencodeAddress($params[1]);
}
call_user_func_array([$this, 'addAnAddress'], $params);
}
if (count($this->to) + count($this->cc) + count($this->bcc) < 1) {
throw new Exception($this->lang('provide_address'), self::STOP_CRITICAL);
}
//Validate From, Sender, and ConfirmReadingTo addresses
foreach (['From', 'Sender', 'ConfirmReadingTo'] as $address_kind) {
if ($this->{$address_kind} === null) {
$this->{$address_kind} = '';
continue;
}
$this->{$address_kind} = trim($this->{$address_kind});
if (empty($this->{$address_kind})) {
continue;
}
$this->{$address_kind} = $this->punyencodeAddress($this->{$address_kind});
if (!static::validateAddress($this->{$address_kind})) {
$error_message = sprintf(
'%s (%s): %s',
$this->lang('invalid_address'),
$address_kind,
$this->{$address_kind}
);
$this->setError($error_message);
$this->edebug($error_message);
if ($this->exceptions) {
throw new Exception($error_message);
}
return false;
}
}
//Set whether the message is multipart/alternative
if ($this->alternativeExists()) {
$this->ContentType = static::CONTENT_TYPE_MULTIPART_ALTERNATIVE;
}
$this->setMessageType();
//Refuse to send an empty message unless we are specifically allowing it
if (!$this->AllowEmpty && empty($this->Body)) {
throw new Exception($this->lang('empty_message'), self::STOP_CRITICAL);
}
//Trim subject consistently
$this->Subject = trim($this->Subject);
//Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
$this->MIMEHeader = '';
$this->MIMEBody = $this->createBody();
//createBody may have added some headers, so retain them
$tempheaders = $this->MIMEHeader;
$this->MIMEHeader = $this->createHeader();
$this->MIMEHeader .= $tempheaders;
//To capture the complete message when using mail(), create
//an extra header list which createHeader() doesn't fold in
if ('mail' === $this->Mailer) {
if (count($this->to) > 0) {
$this->mailHeader .= $this->addrAppend('To', $this->to);
} else {
$this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
}
$this->mailHeader .= $this->headerLine(
'Subject',
$this->encodeHeader($this->secureHeader($this->Subject))
);
}
//Sign with DKIM if enabled
if (
!empty($this->DKIM_domain)
&& !empty($this->DKIM_selector)
&& (!empty($this->DKIM_private_string)
|| (!empty($this->DKIM_private)
&& static::isPermittedPath($this->DKIM_private)
&& file_exists($this->DKIM_private)
)
)
) {
$header_dkim = $this->DKIM_Add(
$this->MIMEHeader . $this->mailHeader,
$this->encodeHeader($this->secureHeader($this->Subject)),
$this->MIMEBody
);
$this->MIMEHeader = static::stripTrailingWSP($this->MIMEHeader) . static::$LE .
static::normalizeBreaks($header_dkim) . static::$LE;
}
return true;
} catch (Exception $exc) {
$this->setError($exc->getMessage());
if ($this->exceptions) {
throw $exc;
}
return false;
}
}
/**
* Actually send a message via the selected mechanism.
*
* @throws Exception
*
* @return bool
*/
public function postSend()
{
try {
//Choose the mailer and send through it
switch ($this->Mailer) {
case 'sendmail':
case 'qmail':
return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
case 'smtp':
return $this->smtpSend($this->MIMEHeader, $this->MIMEBody);
case 'mail':
return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
default:
$sendMethod = $this->Mailer . 'Send';
if (method_exists($this, $sendMethod)) {
return $this->{$sendMethod}($this->MIMEHeader, $this->MIMEBody);
}
return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
}
} catch (Exception $exc) {
$this->setError($exc->getMessage());
$this->edebug($exc->getMessage());
if ($this->Mailer === 'smtp' && $this->SMTPKeepAlive == true && $this->smtp->connected()) {
$this->smtp->reset();
}
if ($this->exceptions) {
throw $exc;
}
}
return false;
}
/**
* Send mail using the $Sendmail program.
*
* @see PHPMailer::$Sendmail
*
* @param string $header The message headers
* @param string $body The message body
*
* @throws Exception
*
* @return bool
*/
protected function sendmailSend($header, $body)
{
if ($this->Mailer === 'qmail') {
$this->edebug('Sending with qmail');
} else {
$this->edebug('Sending with sendmail');
}
$header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
//This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
//A space after `-f` is optional, but there is a long history of its presence
//causing problems, so we don't use one
//Exim docs: https://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
//Sendmail docs: https://www.sendmail.org/~ca/email/man/sendmail.html
//Example problem: https://www.drupal.org/node/1057954
//PHP 5.6 workaround
$sendmail_from_value = ini_get('sendmail_from');
if (empty($this->Sender) && !empty($sendmail_from_value)) {
//PHP config has a sender address we can use
$this->Sender = ini_get('sendmail_from');
}
//CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
if (!empty($this->Sender) && static::validateAddress($this->Sender) && self::isShellSafe($this->Sender)) {
if ($this->Mailer === 'qmail') {
$sendmailFmt = '%s -f%s';
} else {
$sendmailFmt = '%s -oi -f%s -t';
}
} else {
//allow sendmail to choose a default envelope sender. It may
//seem preferable to force it to use the From header as with
//SMTP, but that introduces new problems (see
//<https://github.com/PHPMailer/PHPMailer/issues/2298>), and
//it has historically worked this way.
$sendmailFmt = '%s -oi -t';
}
$sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender);
$this->edebug('Sendmail path: ' . $this->Sendmail);
$this->edebug('Sendmail command: ' . $sendmail);
$this->edebug('Envelope sender: ' . $this->Sender);
$this->edebug("Headers: {$header}");
if ($this->SingleTo) {
foreach ($this->SingleToArray as $toAddr) {
$mail = @popen($sendmail, 'w');
if (!$mail) {
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
$this->edebug("To: {$toAddr}");
fwrite($mail, 'To: ' . $toAddr . "\n");
fwrite($mail, $header);
fwrite($mail, $body);
$result = pclose($mail);
$addrinfo = static::parseAddresses($toAddr, true, $this->CharSet);
$this->doCallback(
($result === 0),
[[$addrinfo['address'], $addrinfo['name']]],
$this->cc,
$this->bcc,
$this->Subject,
$body,
$this->From,
[]
);
$this->edebug("Result: " . ($result === 0 ? 'true' : 'false'));
if (0 !== $result) {
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
}
} else {
$mail = @popen($sendmail, 'w');
if (!$mail) {
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
fwrite($mail, $header);
fwrite($mail, $body);
$result = pclose($mail);
$this->doCallback(
($result === 0),
$this->to,
$this->cc,
$this->bcc,
$this->Subject,
$body,
$this->From,
[]
);
$this->edebug("Result: " . ($result === 0 ? 'true' : 'false'));
if (0 !== $result) {
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
}
return true;
}
/**
* Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters.
* Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows.
*
* @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report
*
* @param string $string The string to be validated
*
* @return bool
*/
protected static function isShellSafe($string)
{
//It's not possible to use shell commands safely (which includes the mail() function) without escapeshellarg,
//but some hosting providers disable it, creating a security problem that we don't want to have to deal with,
//so we don't.
if (!function_exists('escapeshellarg') || !function_exists('escapeshellcmd')) {
return false;
}
if (
escapeshellcmd($string) !== $string
|| !in_array(escapeshellarg($string), ["'$string'", "\"$string\""])
) {
return false;
}
$length = strlen($string);
for ($i = 0; $i < $length; ++$i) {
$c = $string[$i];
//All other characters have a special meaning in at least one common shell, including = and +.
//Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
//Note that this does permit non-Latin alphanumeric characters based on the current locale.
if (!ctype_alnum($c) && strpos('@_-.', $c) === false) {
return false;
}
}
return true;
}
/**
* Check whether a file path is of a permitted type.
* Used to reject URLs and phar files from functions that access local file paths,
* such as addAttachment.
*
* @param string $path A relative or absolute path to a file
*
* @return bool
*/
protected static function isPermittedPath($path)
{
//Matches scheme definition from https://www.rfc-editor.org/rfc/rfc3986#section-3.1
return !preg_match('#^[a-z][a-z\d+.-]*://#i', $path);
}
/**
* Check whether a file path is safe, accessible, and readable.
*
* @param string $path A relative or absolute path to a file
*
* @return bool
*/
protected static function fileIsAccessible($path)
{
if (!static::isPermittedPath($path)) {
return false;
}
$readable = is_file($path);
//If not a UNC path (expected to start with \\), check read permission, see #2069
if (strpos($path, '\\\\') !== 0) {
$readable = $readable && is_readable($path);
}
return $readable;
}
/**
* Send mail using the PHP mail() function.
*
* @see https://www.php.net/manual/en/book.mail.php
*
* @param string $header The message headers
* @param string $body The message body
*
* @throws Exception
*
* @return bool
*/
protected function mailSend($header, $body)
{
$header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
$toArr = [];
foreach ($this->to as $toaddr) {
$toArr[] = $this->addrFormat($toaddr);
}
$to = trim(implode(', ', $toArr));
//If there are no To-addresses (e.g. when sending only to BCC-addresses)
//the following should be added to get a correct DKIM-signature.
//Compare with $this->preSend()
if ($to === '') {
$to = 'undisclosed-recipients:;';
}
$params = null;
//This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
//A space after `-f` is optional, but there is a long history of its presence
//causing problems, so we don't use one
//Exim docs: https://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
//Sendmail docs: https://www.sendmail.org/~ca/email/man/sendmail.html
//Example problem: https://www.drupal.org/node/1057954
//CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
//PHP 5.6 workaround
$sendmail_from_value = ini_get('sendmail_from');
if (empty($this->Sender) && !empty($sendmail_from_value)) {
//PHP config has a sender address we can use
$this->Sender = ini_get('sendmail_from');
}
if (!empty($this->Sender) && static::validateAddress($this->Sender)) {
if (self::isShellSafe($this->Sender)) {
$params = sprintf('-f%s', $this->Sender);
}
$old_from = ini_get('sendmail_from');
ini_set('sendmail_from', $this->Sender);
}
$result = false;
if ($this->SingleTo && count($toArr) > 1) {
foreach ($toArr as $toAddr) {
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
$addrinfo = static::parseAddresses($toAddr, true, $this->CharSet);
$this->doCallback(
$result,
[[$addrinfo['address'], $addrinfo['name']]],
$this->cc,
$this->bcc,
$this->Subject,
$body,
$this->From,
[]
);
}
} else {
$result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
$this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From, []);
}
if (isset($old_from)) {
ini_set('sendmail_from', $old_from);
}
if (!$result) {
throw new Exception($this->lang('instantiate'), self::STOP_CRITICAL);
}
return true;
}
/**
* Get an instance to use for SMTP operations.
* Override this function to load your own SMTP implementation,
* or set one with setSMTPInstance.
*
* @return SMTP
*/
public function getSMTPInstance()
{
if (!is_object($this->smtp)) {
$this->smtp = new SMTP();
}
return $this->smtp;
}
/**
* Provide an instance to use for SMTP operations.
*
* @return SMTP
*/
public function setSMTPInstance(SMTP $smtp)
{
$this->smtp = $smtp;
return $this->smtp;
}
/**
* Provide SMTP XCLIENT attributes
*
* @param string $name Attribute name
* @param ?string $value Attribute value
*
* @return bool
*/
public function setSMTPXclientAttribute($name, $value)
{
if (!in_array($name, SMTP::$xclient_allowed_attributes)) {
return false;
}
if (isset($this->SMTPXClient[$name]) && $value === null) {
unset($this->SMTPXClient[$name]);
} elseif ($value !== null) {
$this->SMTPXClient[$name] = $value;
}
return true;
}
/**
* Get SMTP XCLIENT attributes
*
* @return array
*/
public function getSMTPXclientAttributes()
{
return $this->SMTPXClient;
}
/**
* Send mail via SMTP.
* Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
*
* @see PHPMailer::setSMTPInstance() to use a different class.
*
* @uses \PHPMailer\PHPMailer\SMTP
*
* @param string $header The message headers
* @param string $body The message body
*
* @throws Exception
*
* @return bool
*/
protected function smtpSend($header, $body)
{
$header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
$bad_rcpt = [];
if (!$this->smtpConnect($this->SMTPOptions)) {
throw new Exception($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
}
//If we have recipient addresses that need Unicode support,
//but the server doesn't support it, stop here
if ($this->UseSMTPUTF8 && !$this->smtp->getServerExt('SMTPUTF8')) {
throw new Exception($this->lang('no_smtputf8'), self::STOP_CRITICAL);
}
//Sender already validated in preSend()
if ('' === $this->Sender) {
$smtp_from = $this->From;
} else {
$smtp_from = $this->Sender;
}
if (count($this->SMTPXClient)) {
$this->smtp->xclient($this->SMTPXClient);
}
if (!$this->smtp->mail($smtp_from)) {
$this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
throw new Exception($this->ErrorInfo, self::STOP_CRITICAL);
}
$callbacks = [];
//Attempt to send to all recipients
foreach ([$this->to, $this->cc, $this->bcc] as $togroup) {
foreach ($togroup as $to) {
if (!$this->smtp->recipient($to[0], $this->dsn)) {
$error = $this->smtp->getError();
$bad_rcpt[] = ['to' => $to[0], 'error' => $error['detail']];
$isSent = false;
} else {
$isSent = true;
}
$callbacks[] = ['issent' => $isSent, 'to' => $to[0], 'name' => $to[1]];
}
}
//Only send the DATA command if we have viable recipients
if ((count($this->all_recipients) > count($bad_rcpt)) && !$this->smtp->data($header . $body)) {
throw new Exception($this->lang('data_not_accepted'), self::STOP_CRITICAL);
}
$smtp_transaction_id = $this->smtp->getLastTransactionID();
if ($this->SMTPKeepAlive) {
$this->smtp->reset();
} else {
$this->smtp->quit();
$this->smtp->close();
}
foreach ($callbacks as $cb) {
$this->doCallback(
$cb['issent'],
[[$cb['to'], $cb['name']]],
[],
[],
$this->Subject,
$body,
$this->From,
['smtp_transaction_id' => $smtp_transaction_id]
);
}
//Create error message for any bad addresses
if (count($bad_rcpt) > 0) {
$errstr = '';
foreach ($bad_rcpt as $bad) {
$errstr .= $bad['to'] . ': ' . $bad['error'];
}
throw new Exception($this->lang('recipients_failed') . $errstr, self::STOP_CONTINUE);
}
return true;
}
/**
* Initiate a connection to an SMTP server.
* Returns false if the operation failed.
*
* @param array $options An array of options compatible with stream_context_create()
*
* @throws Exception
*
* @uses \PHPMailer\PHPMailer\SMTP
*
* @return bool
*/
public function smtpConnect($options = null)
{
if (null === $this->smtp) {
$this->smtp = $this->getSMTPInstance();
}
//If no options are provided, use whatever is set in the instance
if (null === $options) {
$options = $this->SMTPOptions;
}
//Already connected?
if ($this->smtp->connected()) {
return true;
}
$this->smtp->setTimeout($this->Timeout);
$this->smtp->setDebugLevel($this->SMTPDebug);
$this->smtp->setDebugOutput($this->Debugoutput);
$this->smtp->setVerp($this->do_verp);
$this->smtp->setSMTPUTF8($this->UseSMTPUTF8);
if ($this->Host === null) {
$this->Host = 'localhost';
}
$hosts = explode(';', $this->Host);
$lastexception = null;
foreach ($hosts as $hostentry) {
$hostinfo = [];
if (
!preg_match(
'/^(?:(ssl|tls):\/\/)?(.+?)(?::(\d+))?$/',
trim($hostentry),
$hostinfo
)
) {
$this->edebug($this->lang('invalid_hostentry') . ' ' . trim($hostentry));
//Not a valid host entry
continue;
}
//$hostinfo[1]: optional ssl or tls prefix
//$hostinfo[2]: the hostname
//$hostinfo[3]: optional port number
//The host string prefix can temporarily override the current setting for SMTPSecure
//If it's not specified, the default value is used
//Check the host name is a valid name or IP address before trying to use it
if (!static::isValidHost($hostinfo[2])) {
$this->edebug($this->lang('invalid_host') . ' ' . $hostinfo[2]);
continue;
}
$prefix = '';
$secure = $this->SMTPSecure;
$tls = (static::ENCRYPTION_STARTTLS === $this->SMTPSecure);
if ('ssl' === $hostinfo[1] || ('' === $hostinfo[1] && static::ENCRYPTION_SMTPS === $this->SMTPSecure)) {
$prefix = 'ssl://';
$tls = false; //Can't have SSL and TLS at the same time
$secure = static::ENCRYPTION_SMTPS;
} elseif ('tls' === $hostinfo[1]) {
$tls = true;
//TLS doesn't use a prefix
$secure = static::ENCRYPTION_STARTTLS;
}
//Do we need the OpenSSL extension?
$sslext = defined('OPENSSL_ALGO_SHA256');
if (static::ENCRYPTION_STARTTLS === $secure || static::ENCRYPTION_SMTPS === $secure) {
//Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
if (!$sslext) {
throw new Exception($this->lang('extension_missing') . 'openssl', self::STOP_CRITICAL);
}
}
$host = $hostinfo[2];
$port = $this->Port;
if (
array_key_exists(3, $hostinfo) &&
is_numeric($hostinfo[3]) &&
$hostinfo[3] > 0 &&
$hostinfo[3] < 65536
) {
$port = (int) $hostinfo[3];
}
if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
try {
if ($this->Helo) {
$hello = $this->Helo;
} else {
$hello = $this->serverHostname();
}
$this->smtp->hello($hello);
//Automatically enable TLS encryption if:
//* it's not disabled
//* we are not connecting to localhost
//* we have openssl extension
//* we are not already using SSL
//* the server offers STARTTLS
if (
$this->SMTPAutoTLS &&
$this->Host !== 'localhost' &&
$sslext &&
$secure !== 'ssl' &&
$this->smtp->getServerExt('STARTTLS')
) {
$tls = true;
}
if ($tls) {
if (!$this->smtp->startTLS()) {
$message = $this->getSmtpErrorMessage('connect_host');
throw new Exception($message);
}
//We must resend EHLO after TLS negotiation
$this->smtp->hello($hello);
}
if (
$this->SMTPAuth && !$this->smtp->authenticate(
$this->Username,
$this->Password,
$this->AuthType,
$this->oauth
)
) {
throw new Exception($this->lang('authenticate'));
}
return true;
} catch (Exception $exc) {
$lastexception = $exc;
$this->edebug($exc->getMessage());
//We must have connected, but then failed TLS or Auth, so close connection nicely
$this->smtp->quit();
}
}
}
//If we get here, all connection attempts have failed, so close connection hard
$this->smtp->close();
//As we've caught all exceptions, just report whatever the last one was
if ($this->exceptions && null !== $lastexception) {
throw $lastexception;
}
if ($this->exceptions) {
// no exception was thrown, likely $this->smtp->connect() failed
$message = $this->getSmtpErrorMessage('connect_host');
throw new Exception($message);
}
return false;
}
/**
* Close the active SMTP session if one exists.
*/
public function smtpClose()
{
if ((null !== $this->smtp) && $this->smtp->connected()) {
$this->smtp->quit();
$this->smtp->close();
}
}
/**
* Set the language for error messages.
* The default language is English.
*
* @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
* Optionally, the language code can be enhanced with a 4-character
* script annotation and/or a 2-character country annotation.
* @param string $lang_path Path to the language file directory, with trailing separator (slash)
* Do not set this from user input!
*
* @return bool Returns true if the requested language was loaded, false otherwise.
*/
public function setLanguage($langcode = 'en', $lang_path = '')
{
//Backwards compatibility for renamed language codes
$renamed_langcodes = [
'br' => 'pt_br',
'cz' => 'cs',
'dk' => 'da',
'no' => 'nb',
'se' => 'sv',
'rs' => 'sr',
'tg' => 'tl',
'am' => 'hy',
];
if (array_key_exists($langcode, $renamed_langcodes)) {
$langcode = $renamed_langcodes[$langcode];
}
//Define full set of translatable strings in English
$PHPMAILER_LANG = [
'authenticate' => 'SMTP Error: Could not authenticate.',
'buggy_php' => 'Your version of PHP is affected by a bug that may result in corrupted messages.' .
' To fix it, switch to sending using SMTP, disable the mail.add_x_header option in' .
' your php.ini, switch to MacOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+.',
'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
'data_not_accepted' => 'SMTP Error: data not accepted.',
'empty_message' => 'Message body empty',
'encoding' => 'Unknown encoding: ',
'execute' => 'Could not execute: ',
'extension_missing' => 'Extension missing: ',
'file_access' => 'Could not access file: ',
'file_open' => 'File Error: Could not open file: ',
'from_failed' => 'The following From address failed: ',
'instantiate' => 'Could not instantiate mail function.',
'invalid_address' => 'Invalid address: ',
'invalid_header' => 'Invalid header name or value',
'invalid_hostentry' => 'Invalid hostentry: ',
'invalid_host' => 'Invalid host: ',
'mailer_not_supported' => ' mailer is not supported.',
'provide_address' => 'You must provide at least one recipient email address.',
'recipients_failed' => 'SMTP Error: The following recipients failed: ',
'signing' => 'Signing Error: ',
'smtp_code' => 'SMTP code: ',
'smtp_code_ex' => 'Additional SMTP info: ',
'smtp_connect_failed' => 'SMTP connect() failed.',
'smtp_detail' => 'Detail: ',
'smtp_error' => 'SMTP server error: ',
'variable_set' => 'Cannot set or reset variable: ',
'no_smtputf8' => 'Server does not support SMTPUTF8 needed to send to Unicode addresses',
];
if (empty($lang_path)) {
//Calculate an absolute path so it can work if CWD is not here
$lang_path = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR;
}
//Validate $langcode
$foundlang = true;
$langcode = strtolower($langcode);
if (
!preg_match('/^(?P<lang>[a-z]{2})(?P<script>_[a-z]{4})?(?P<country>_[a-z]{2})?$/', $langcode, $matches)
&& $langcode !== 'en'
) {
$foundlang = false;
$langcode = 'en';
}
//There is no English translation file
if ('en' !== $langcode) {
$langcodes = [];
if (!empty($matches['script']) && !empty($matches['country'])) {
$langcodes[] = $matches['lang'] . $matches['script'] . $matches['country'];
}
if (!empty($matches['country'])) {
$langcodes[] = $matches['lang'] . $matches['country'];
}
if (!empty($matches['script'])) {
$langcodes[] = $matches['lang'] . $matches['script'];
}
$langcodes[] = $matches['lang'];
//Try and find a readable language file for the requested language.
$foundFile = false;
foreach ($langcodes as $code) {
$lang_file = $lang_path . 'phpmailer.lang-' . $code . '.php';
if (static::fileIsAccessible($lang_file)) {
$foundFile = true;
break;
}
}
if ($foundFile === false) {
$foundlang = false;
} else {
$lines = file($lang_file);
foreach ($lines as $line) {
//Translation file lines look like this:
//$PHPMAILER_LANG['authenticate'] = 'SMTP-Fehler: Authentifizierung fehlgeschlagen.';
//These files are parsed as text and not PHP so as to avoid the possibility of code injection
//See https://blog.stevenlevithan.com/archives/match-quoted-string
$matches = [];
if (
preg_match(
'/^\$PHPMAILER_LANG\[\'([a-z\d_]+)\'\]\s*=\s*(["\'])(.+)*?\2;/',
$line,
$matches
) &&
//Ignore unknown translation keys
array_key_exists($matches[1], $PHPMAILER_LANG)
) {
//Overwrite language-specific strings so we'll never have missing translation keys.
$PHPMAILER_LANG[$matches[1]] = (string)$matches[3];
}
}
}
}
$this->language = $PHPMAILER_LANG;
return $foundlang; //Returns false if language not found
}
/**
* Get the array of strings for the current language.
*
* @return array
*/
public function getTranslations()
{
if (empty($this->language)) {
$this->setLanguage(); // Set the default language.
}
return $this->language;
}
/**
* Create recipient headers.
*
* @param string $type
* @param array $addr An array of recipients,
* where each recipient is a 2-element indexed array with element 0 containing an address
* and element 1 containing a name, like:
* [['joe@example.com', 'Joe User'], ['zoe@example.com', 'Zoe User']]
*
* @return string
*/
public function addrAppend($type, $addr)
{
$addresses = [];
foreach ($addr as $address) {
$addresses[] = $this->addrFormat($address);
}
return $type . ': ' . implode(', ', $addresses) . static::$LE;
}
/**
* Format an address for use in a message header.
*
* @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name like
* ['joe@example.com', 'Joe User']
*
* @return string
*/
public function addrFormat($addr)
{
if (!isset($addr[1]) || ($addr[1] === '')) { //No name provided
return $this->secureHeader($addr[0]);
}
return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') .
' <' . $this->secureHeader($addr[0]) . '>';
}
/**
* Word-wrap message.
* For use with mailers that do not automatically perform wrapping
* and for quoted-printable encoded messages.
* Original written by philippe.
*
* @param string $message The message to wrap
* @param int $length The line length to wrap to
* @param bool $qp_mode Whether to run in Quoted-Printable mode
*
* @return string
*/
public function wrapText($message, $length, $qp_mode = false)
{
if ($qp_mode) {
$soft_break = sprintf(' =%s', static::$LE);
} else {
$soft_break = static::$LE;
}
//If utf-8 encoding is used, we will need to make sure we don't
//split multibyte characters when we wrap
$is_utf8 = static::CHARSET_UTF8 === strtolower($this->CharSet);
$lelen = strlen(static::$LE);
$crlflen = strlen(static::$LE);
$message = static::normalizeBreaks($message);
//Remove a trailing line break
if (substr($message, -$lelen) === static::$LE) {
$message = substr($message, 0, -$lelen);
}
//Split message into lines
$lines = explode(static::$LE, $message);
//Message will be rebuilt in here
$message = '';
foreach ($lines as $line) {
$words = explode(' ', $line);
$buf = '';
$firstword = true;
foreach ($words as $word) {
if ($qp_mode && (strlen($word) > $length)) {
$space_left = $length - strlen($buf) - $crlflen;
if (!$firstword) {
if ($space_left > 20) {
$len = $space_left;
if ($is_utf8) {
$len = $this->utf8CharBoundary($word, $len);
} elseif ('=' === substr($word, $len - 1, 1)) {
--$len;
} elseif ('=' === substr($word, $len - 2, 1)) {
$len -= 2;
}
$part = substr($word, 0, $len);
$word = substr($word, $len);
$buf .= ' ' . $part;
$message .= $buf . sprintf('=%s', static::$LE);
} else {
$message .= $buf . $soft_break;
}
$buf = '';
}
while ($word !== '') {
if ($length <= 0) {
break;
}
$len = $length;
if ($is_utf8) {
$len = $this->utf8CharBoundary($word, $len);
} elseif ('=' === substr($word, $len - 1, 1)) {
--$len;
} elseif ('=' === substr($word, $len - 2, 1)) {
$len -= 2;
}
$part = substr($word, 0, $len);
$word = (string) substr($word, $len);
if ($word !== '') {
$message .= $part . sprintf('=%s', static::$LE);
} else {
$buf = $part;
}
}
} else {
$buf_o = $buf;
if (!$firstword) {
$buf .= ' ';
}
$buf .= $word;
if ('' !== $buf_o && strlen($buf) > $length) {
$message .= $buf_o . $soft_break;
$buf = $word;
}
}
$firstword = false;
}
$message .= $buf . static::$LE;
}
return $message;
}
/**
* Find the last character boundary prior to $maxLength in a utf-8
* quoted-printable encoded string.
* Original written by Colin Brown.
*
* @param string $encodedText utf-8 QP text
* @param int $maxLength Find the last character boundary prior to this length
*
* @return int
*/
public function utf8CharBoundary($encodedText, $maxLength)
{
$foundSplitPos = false;
$lookBack = 3;
while (!$foundSplitPos) {
$lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
$encodedCharPos = strpos($lastChunk, '=');
if (false !== $encodedCharPos) {
//Found start of encoded character byte within $lookBack block.
//Check the encoded byte value (the 2 chars after the '=')
$hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
$dec = hexdec($hex);
if ($dec < 128) {
//Single byte character.
//If the encoded char was found at pos 0, it will fit
//otherwise reduce maxLength to start of the encoded char
if ($encodedCharPos > 0) {
$maxLength -= $lookBack - $encodedCharPos;
}
$foundSplitPos = true;
} elseif ($dec >= 192) {
//First byte of a multi byte character
//Reduce maxLength to split at start of character
$maxLength -= $lookBack - $encodedCharPos;
$foundSplitPos = true;
} elseif ($dec < 192) {
//Middle byte of a multi byte character, look further back
$lookBack += 3;
}
} else {
//No encoded character found
$foundSplitPos = true;
}
}
return $maxLength;
}
/**
* Apply word wrapping to the message body.
* Wraps the message body to the number of chars set in the WordWrap property.
* You should only do this to plain-text bodies as wrapping HTML tags may break them.
* This is called automatically by createBody(), so you don't need to call it yourself.
*/
public function setWordWrap()
{
if ($this->WordWrap < 1) {
return;
}
switch ($this->message_type) {
case 'alt':
case 'alt_inline':
case 'alt_attach':
case 'alt_inline_attach':
$this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap);
break;
default:
$this->Body = $this->wrapText($this->Body, $this->WordWrap);
break;
}
}
/**
* Assemble message headers.
*
* @return string The assembled headers
*/
public function createHeader()
{
$result = '';
$result .= $this->headerLine('Date', '' === $this->MessageDate ? self::rfcDate() : $this->MessageDate);
//The To header is created automatically by mail(), so needs to be omitted here
if ('mail' !== $this->Mailer) {
if ($this->SingleTo) {
foreach ($this->to as $toaddr) {
$this->SingleToArray[] = $this->addrFormat($toaddr);
}
} elseif (count($this->to) > 0) {
$result .= $this->addrAppend('To', $this->to);
} elseif (count($this->cc) === 0) {
$result .= $this->headerLine('To', 'undisclosed-recipients:;');
}
}
$result .= $this->addrAppend('From', [[trim($this->From), $this->FromName]]);
//sendmail and mail() extract Cc from the header before sending
if (count($this->cc) > 0) {
$result .= $this->addrAppend('Cc', $this->cc);
}
//sendmail and mail() extract Bcc from the header before sending
if (
(
'sendmail' === $this->Mailer || 'qmail' === $this->Mailer || 'mail' === $this->Mailer
)
&& count($this->bcc) > 0
) {
$result .= $this->addrAppend('Bcc', $this->bcc);
}
if (count($this->ReplyTo) > 0) {
$result .= $this->addrAppend('Reply-To', $this->ReplyTo);
}
//mail() sets the subject itself
if ('mail' !== $this->Mailer) {
$result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
}
//Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4
//https://www.rfc-editor.org/rfc/rfc5322#section-3.6.4
if (
'' !== $this->MessageID &&
preg_match(
'/^<((([a-z\d!#$%&\'*+\/=?^_`{|}~-]+(\.[a-z\d!#$%&\'*+\/=?^_`{|}~-]+)*)' .
'|("(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21\x23-\x5B\x5D-\x7E])' .
'|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*"))@(([a-z\d!#$%&\'*+\/=?^_`{|}~-]+' .
'(\.[a-z\d!#$%&\'*+\/=?^_`{|}~-]+)*)|(\[(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]' .
'|[\x21-\x5A\x5E-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*\])))>$/Di',
$this->MessageID
)
) {
$this->lastMessageID = $this->MessageID;
} else {
$this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname());
}
$result .= $this->headerLine('Message-ID', $this->lastMessageID);
if (null !== $this->Priority) {
$result .= $this->headerLine('X-Priority', $this->Priority);
}
if ('' === $this->XMailer) {
//Empty string for default X-Mailer header
$result .= $this->headerLine(
'X-Mailer',
'PHPMailer ' . self::VERSION . ' (https://github.com/PHPMailer/PHPMailer)'
);
} elseif (is_string($this->XMailer) && trim($this->XMailer) !== '') {
//Some string
$result .= $this->headerLine('X-Mailer', trim($this->XMailer));
} //Other values result in no X-Mailer header
if ('' !== $this->ConfirmReadingTo) {
$result .= $this->headerLine('Disposition-Notification-To', '<' . $this->ConfirmReadingTo . '>');
}
//Add custom headers
foreach ($this->CustomHeader as $header) {
$result .= $this->headerLine(
trim($header[0]),
$this->encodeHeader(trim($header[1]))
);
}
if (!$this->sign_key_file) {
$result .= $this->headerLine('MIME-Version', '1.0');
$result .= $this->getMailMIME();
}
return $result;
}
/**
* Get the message MIME type headers.
*
* @return string
*/
public function getMailMIME()
{
$result = '';
$ismultipart = true;
switch ($this->message_type) {
case 'inline':
$result .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
$result .= $this->textLine(' boundary="' . $this->boundary[1] . '"');
break;
case 'attach':
case 'inline_attach':
case 'alt_attach':
case 'alt_inline_attach':
$result .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_MIXED . ';');
$result .= $this->textLine(' boundary="' . $this->boundary[1] . '"');
break;
case 'alt':
case 'alt_inline':
$result .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_ALTERNATIVE . ';');
$result .= $this->textLine(' boundary="' . $this->boundary[1] . '"');
break;
default:
//Catches case 'plain': and case '':
$result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet);
$ismultipart = false;
break;
}
//RFC1341 part 5 says 7bit is assumed if not specified
if (static::ENCODING_7BIT !== $this->Encoding) {
//RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
if ($ismultipart) {
if (static::ENCODING_8BIT === $this->Encoding) {
$result .= $this->headerLine('Content-Transfer-Encoding', static::ENCODING_8BIT);
}
//The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
} else {
$result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding);
}
}
return $result;
}
/**
* Returns the whole MIME message.
* Includes complete headers and body.
* Only valid post preSend().
*
* @see PHPMailer::preSend()
*
* @return string
*/
public function getSentMIMEMessage()
{
return static::stripTrailingWSP($this->MIMEHeader . $this->mailHeader) .
static::$LE . static::$LE . $this->MIMEBody;
}
/**
* Create a unique ID to use for boundaries.
*
* @return string
*/
protected function generateId()
{
$len = 32; //32 bytes = 256 bits
$bytes = '';
if (function_exists('random_bytes')) {
try {
$bytes = random_bytes($len);
} catch (\Exception $e) {
//Do nothing
}
} elseif (function_exists('openssl_random_pseudo_bytes')) {
/** @noinspection CryptographicallySecureRandomnessInspection */
$bytes = openssl_random_pseudo_bytes($len);
}
if ($bytes === '') {
//We failed to produce a proper random string, so make do.
//Use a hash to force the length to the same as the other methods
$bytes = hash('sha256', uniqid((string) mt_rand(), true), true);
}
//We don't care about messing up base64 format here, just want a random string
return str_replace(['=', '+', '/'], '', base64_encode(hash('sha256', $bytes, true)));
}
/**
* Assemble the message body.
* Returns an empty string on failure.
*
* @throws Exception
*
* @return string The assembled message body
*/
public function createBody()
{
$body = '';
//Create unique IDs and preset boundaries
$this->setBoundaries();
if ($this->sign_key_file) {
$body .= $this->getMailMIME() . static::$LE;
}
$this->setWordWrap();
$bodyEncoding = $this->Encoding;
$bodyCharSet = $this->CharSet;
//Can we do a 7-bit downgrade?
if ($this->UseSMTPUTF8) {
$bodyEncoding = static::ENCODING_8BIT;
} elseif (static::ENCODING_8BIT === $bodyEncoding && !$this->has8bitChars($this->Body)) {
$bodyEncoding = static::ENCODING_7BIT;
//All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
$bodyCharSet = static::CHARSET_ASCII;
}
//If lines are too long, and we're not already using an encoding that will shorten them,
//change to quoted-printable transfer encoding for the body part only
if (static::ENCODING_BASE64 !== $this->Encoding && static::hasLineLongerThanMax($this->Body)) {
$bodyEncoding = static::ENCODING_QUOTED_PRINTABLE;
}
$altBodyEncoding = $this->Encoding;
$altBodyCharSet = $this->CharSet;
//Can we do a 7-bit downgrade?
if (static::ENCODING_8BIT === $altBodyEncoding && !$this->has8bitChars($this->AltBody)) {
$altBodyEncoding = static::ENCODING_7BIT;
//All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
$altBodyCharSet = static::CHARSET_ASCII;
}
//If lines are too long, and we're not already using an encoding that will shorten them,
//change to quoted-printable transfer encoding for the alt body part only
if (static::ENCODING_BASE64 !== $altBodyEncoding && static::hasLineLongerThanMax($this->AltBody)) {
$altBodyEncoding = static::ENCODING_QUOTED_PRINTABLE;
}
//Use this as a preamble in all multipart message types
$mimepre = '';
switch ($this->message_type) {
case 'inline':
$body .= $mimepre;
$body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
$body .= $this->encodeString($this->Body, $bodyEncoding);
$body .= static::$LE;
$body .= $this->attachAll('inline', $this->boundary[1]);
break;
case 'attach':
$body .= $mimepre;
$body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
$body .= $this->encodeString($this->Body, $bodyEncoding);
$body .= static::$LE;
$body .= $this->attachAll('attachment', $this->boundary[1]);
break;
case 'inline_attach':
$body .= $mimepre;
$body .= $this->textLine('--' . $this->boundary[1]);
$body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
$body .= $this->textLine(' boundary="' . $this->boundary[2] . '";');
$body .= $this->textLine(' type="' . static::CONTENT_TYPE_TEXT_HTML . '"');
$body .= static::$LE;
$body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding);
$body .= $this->encodeString($this->Body, $bodyEncoding);
$body .= static::$LE;
$body .= $this->attachAll('inline', $this->boundary[2]);
$body .= static::$LE;
$body .= $this->attachAll('attachment', $this->boundary[1]);
break;
case 'alt':
$body .= $mimepre;
$body .= $this->getBoundary(
$this->boundary[1],
$altBodyCharSet,
static::CONTENT_TYPE_PLAINTEXT,
$altBodyEncoding
);
$body .= $this->encodeString($this->AltBody, $altBodyEncoding);
$body .= static::$LE;
$body .= $this->getBoundary(
$this->boundary[1],
$bodyCharSet,
static::CONTENT_TYPE_TEXT_HTML,
$bodyEncoding
);
$body .= $this->encodeString($this->Body, $bodyEncoding);
$body .= static::$LE;
if (!empty($this->Ical)) {
$method = static::ICAL_METHOD_REQUEST;
foreach (static::$IcalMethods as $imethod) {
if (stripos($this->Ical, 'METHOD:' . $imethod) !== false) {
$method = $imethod;
break;
}
}
$body .= $this->getBoundary(
$this->boundary[1],
'',
static::CONTENT_TYPE_TEXT_CALENDAR . '; method=' . $method,
''
);
$body .= $this->encodeString($this->Ical, $this->Encoding);
$body .= static::$LE;
}
$body .= $this->endBoundary($this->boundary[1]);
break;
case 'alt_inline':
$body .= $mimepre;
$body .= $this->getBoundary(
$this->boundary[1],
$altBodyCharSet,
static::CONTENT_TYPE_PLAINTEXT,
$altBodyEncoding
);
$body .= $this->encodeString($this->AltBody, $altBodyEncoding);
$body .= static::$LE;
$body .= $this->textLine('--' . $this->boundary[1]);
$body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
$body .= $this->textLine(' boundary="' . $this->boundary[2] . '";');
$body .= $this->textLine(' type="' . static::CONTENT_TYPE_TEXT_HTML . '"');
$body .= static::$LE;
$body .= $this->getBoundary(
$this->boundary[2],
$bodyCharSet,
static::CONTENT_TYPE_TEXT_HTML,
$bodyEncoding
);
$body .= $this->encodeString($this->Body, $bodyEncoding);
$body .= static::$LE;
$body .= $this->attachAll('inline', $this->boundary[2]);
$body .= static::$LE;
$body .= $this->endBoundary($this->boundary[1]);
break;
case 'alt_attach':
$body .= $mimepre;
$body .= $this->textLine('--' . $this->boundary[1]);
$body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_ALTERNATIVE . ';');
$body .= $this->textLine(' boundary="' . $this->boundary[2] . '"');
$body .= static::$LE;
$body .= $this->getBoundary(
$this->boundary[2],
$altBodyCharSet,
static::CONTENT_TYPE_PLAINTEXT,
$altBodyEncoding
);
$body .= $this->encodeString($this->AltBody, $altBodyEncoding);
$body .= static::$LE;
$body .= $this->getBoundary(
$this->boundary[2],
$bodyCharSet,
static::CONTENT_TYPE_TEXT_HTML,
$bodyEncoding
);
$body .= $this->encodeString($this->Body, $bodyEncoding);
$body .= static::$LE;
if (!empty($this->Ical)) {
$method = static::ICAL_METHOD_REQUEST;
foreach (static::$IcalMethods as $imethod) {
if (stripos($this->Ical, 'METHOD:' . $imethod) !== false) {
$method = $imethod;
break;
}
}
$body .= $this->getBoundary(
$this->boundary[2],
'',
static::CONTENT_TYPE_TEXT_CALENDAR . '; method=' . $method,
''
);
$body .= $this->encodeString($this->Ical, $this->Encoding);
}
$body .= $this->endBoundary($this->boundary[2]);
$body .= static::$LE;
$body .= $this->attachAll('attachment', $this->boundary[1]);
break;
case 'alt_inline_attach':
$body .= $mimepre;
$body .= $this->textLine('--' . $this->boundary[1]);
$body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_ALTERNATIVE . ';');
$body .= $this->textLine(' boundary="' . $this->boundary[2] . '"');
$body .= static::$LE;
$body .= $this->getBoundary(
$this->boundary[2],
$altBodyCharSet,
static::CONTENT_TYPE_PLAINTEXT,
$altBodyEncoding
);
$body .= $this->encodeString($this->AltBody, $altBodyEncoding);
$body .= static::$LE;
$body .= $this->textLine('--' . $this->boundary[2]);
$body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
$body .= $this->textLine(' boundary="' . $this->boundary[3] . '";');
$body .= $this->textLine(' type="' . static::CONTENT_TYPE_TEXT_HTML . '"');
$body .= static::$LE;
$body .= $this->getBoundary(
$this->boundary[3],
$bodyCharSet,
static::CONTENT_TYPE_TEXT_HTML,
$bodyEncoding
);
$body .= $this->encodeString($this->Body, $bodyEncoding);
$body .= static::$LE;
$body .= $this->attachAll('inline', $this->boundary[3]);
$body .= static::$LE;
$body .= $this->endBoundary($this->boundary[2]);
$body .= static::$LE;
$body .= $this->attachAll('attachment', $this->boundary[1]);
break;
default:
//Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types
//Reset the `Encoding` property in case we changed it for line length reasons
$this->Encoding = $bodyEncoding;
$body .= $this->encodeString($this->Body, $this->Encoding);
break;
}
if ($this->isError()) {
$body = '';
if ($this->exceptions) {
throw new Exception($this->lang('empty_message'), self::STOP_CRITICAL);
}
} elseif ($this->sign_key_file) {
try {
if (!defined('PKCS7_TEXT')) {
throw new Exception($this->lang('extension_missing') . 'openssl');
}
$file = tempnam(sys_get_temp_dir(), 'srcsign');
$signed = tempnam(sys_get_temp_dir(), 'mailsign');
file_put_contents($file, $body);
//Workaround for PHP bug https://bugs.php.net/bug.php?id=69197
if (empty($this->sign_extracerts_file)) {
$sign = @openssl_pkcs7_sign(
$file,
$signed,
'file://' . realpath($this->sign_cert_file),
['file://' . realpath($this->sign_key_file), $this->sign_key_pass],
[]
);
} else {
$sign = @openssl_pkcs7_sign(
$file,
$signed,
'file://' . realpath($this->sign_cert_file),
['file://' . realpath($this->sign_key_file), $this->sign_key_pass],
[],
PKCS7_DETACHED,
$this->sign_extracerts_file
);
}
@unlink($file);
if ($sign) {
$body = file_get_contents($signed);
@unlink($signed);
//The message returned by openssl contains both headers and body, so need to split them up
$parts = explode("\n\n", $body, 2);
$this->MIMEHeader .= $parts[0] . static::$LE . static::$LE;
$body = $parts[1];
} else {
@unlink($signed);
throw new Exception($this->lang('signing') . openssl_error_string());
}
} catch (Exception $exc) {
$body = '';
if ($this->exceptions) {
throw $exc;
}
}
}
return $body;
}
/**
* Get the boundaries that this message will use
* @return array
*/
public function getBoundaries()
{
if (empty($this->boundary)) {
$this->setBoundaries();
}
return $this->boundary;
}
/**
* Return the start of a message boundary.
*
* @param string $boundary
* @param string $charSet
* @param string $contentType
* @param string $encoding
*
* @return string
*/
protected function getBoundary($boundary, $charSet, $contentType, $encoding)
{
$result = '';
if ('' === $charSet) {
$charSet = $this->CharSet;
}
if ('' === $contentType) {
$contentType = $this->ContentType;
}
if ('' === $encoding) {
$encoding = $this->Encoding;
}
$result .= $this->textLine('--' . $boundary);
$result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
$result .= static::$LE;
//RFC1341 part 5 says 7bit is assumed if not specified
if (static::ENCODING_7BIT !== $encoding) {
$result .= $this->headerLine('Content-Transfer-Encoding', $encoding);
}
$result .= static::$LE;
return $result;
}
/**
* Return the end of a message boundary.
*
* @param string $boundary
*
* @return string
*/
protected function endBoundary($boundary)
{
return static::$LE . '--' . $boundary . '--' . static::$LE;
}
/**
* Set the message type.
* PHPMailer only supports some preset message types, not arbitrary MIME structures.
*/
protected function setMessageType()
{
$type = [];
if ($this->alternativeExists()) {
$type[] = 'alt';
}
if ($this->inlineImageExists()) {
$type[] = 'inline';
}
if ($this->attachmentExists()) {
$type[] = 'attach';
}
$this->message_type = implode('_', $type);
if ('' === $this->message_type) {
//The 'plain' message_type refers to the message having a single body element, not that it is plain-text
$this->message_type = 'plain';
}
}
/**
* Format a header line.
*
* @param string $name
* @param string|int $value
*
* @return string
*/
public function headerLine($name, $value)
{
return $name . ': ' . $value . static::$LE;
}
/**
* Return a formatted mail line.
*
* @param string $value
*
* @return string
*/
public function textLine($value)
{
return $value . static::$LE;
}
/**
* Add an attachment from a path on the filesystem.
* Never use a user-supplied path to a file!
* Returns false if the file could not be found or read.
* Explicitly *does not* support passing URLs; PHPMailer is not an HTTP client.
* If you need to do that, fetch the resource yourself and pass it in via a local file or string.
*
* @param string $path Path to the attachment
* @param string $name Overrides the attachment name
* @param string $encoding File encoding (see $Encoding)
* @param string $type MIME type, e.g. `image/jpeg`; determined automatically from $path if not specified
* @param string $disposition Disposition to use
*
* @throws Exception
*
* @return bool
*/
public function addAttachment(
$path,
$name = '',
$encoding = self::ENCODING_BASE64,
$type = '',
$disposition = 'attachment'
) {
try {
if (!static::fileIsAccessible($path)) {
throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
}
//If a MIME type is not specified, try to work it out from the file name
if ('' === $type) {
$type = static::filenameToType($path);
}
$filename = (string) static::mb_pathinfo($path, PATHINFO_BASENAME);
if ('' === $name) {
$name = $filename;
}
if (!$this->validateEncoding($encoding)) {
throw new Exception($this->lang('encoding') . $encoding);
}
$this->attachment[] = [
0 => $path,
1 => $filename,
2 => $name,
3 => $encoding,
4 => $type,
5 => false, //isStringAttachment
6 => $disposition,
7 => $name,
];
} catch (Exception $exc) {
$this->setError($exc->getMessage());
$this->edebug($exc->getMessage());
if ($this->exceptions) {
throw $exc;
}
return false;
}
return true;
}
/**
* Return the array of attachments.
*
* @return array
*/
public function getAttachments()
{
return $this->attachment;
}
/**
* Attach all file, string, and binary attachments to the message.
* Returns an empty string on failure.
*
* @param string $disposition_type
* @param string $boundary
*
* @throws Exception
*
* @return string
*/
protected function attachAll($disposition_type, $boundary)
{
//Return text of body
$mime = [];
$cidUniq = [];
$incl = [];
//Add all attachments
foreach ($this->attachment as $attachment) {
//Check if it is a valid disposition_filter
if ($attachment[6] === $disposition_type) {
//Check for string attachment
$string = '';
$path = '';
$bString = $attachment[5];
if ($bString) {
$string = $attachment[0];
} else {
$path = $attachment[0];
}
$inclhash = hash('sha256', serialize($attachment));
if (in_array($inclhash, $incl, true)) {
continue;
}
$incl[] = $inclhash;
$name = $attachment[2];
$encoding = $attachment[3];
$type = $attachment[4];
$disposition = $attachment[6];
$cid = $attachment[7];
if ('inline' === $disposition && array_key_exists($cid, $cidUniq)) {
continue;
}
$cidUniq[$cid] = true;
$mime[] = sprintf('--%s%s', $boundary, static::$LE);
//Only include a filename property if we have one
if (!empty($name)) {
$mime[] = sprintf(
'Content-Type: %s; name=%s%s',
$type,
static::quotedString($this->encodeHeader($this->secureHeader($name))),
static::$LE
);
} else {
$mime[] = sprintf(
'Content-Type: %s%s',
$type,
static::$LE
);
}
//RFC1341 part 5 says 7bit is assumed if not specified
if (static::ENCODING_7BIT !== $encoding) {
$mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, static::$LE);
}
//Only set Content-IDs on inline attachments
if ((string) $cid !== '' && $disposition === 'inline') {
$mime[] = 'Content-ID: <' . $this->encodeHeader($this->secureHeader($cid)) . '>' . static::$LE;
}
//Allow for bypassing the Content-Disposition header
if (!empty($disposition)) {
$encoded_name = $this->encodeHeader($this->secureHeader($name));
if (!empty($encoded_name)) {
$mime[] = sprintf(
'Content-Disposition: %s; filename=%s%s',
$disposition,
static::quotedString($encoded_name),
static::$LE . static::$LE
);
} else {
$mime[] = sprintf(
'Content-Disposition: %s%s',
$disposition,
static::$LE . static::$LE
);
}
} else {
$mime[] = static::$LE;
}
//Encode as string attachment
if ($bString) {
$mime[] = $this->encodeString($string, $encoding);
} else {
$mime[] = $this->encodeFile($path, $encoding);
}
if ($this->isError()) {
return '';
}
$mime[] = static::$LE;
}
}
$mime[] = sprintf('--%s--%s', $boundary, static::$LE);
return implode('', $mime);
}
/**
* Encode a file attachment in requested format.
* Returns an empty string on failure.
*
* @param string $path The full path to the file
* @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
*
* @return string
*/
protected function encodeFile($path, $encoding = self::ENCODING_BASE64)
{
try {
if (!static::fileIsAccessible($path)) {
throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE);
}
$file_buffer = file_get_contents($path);
if (false === $file_buffer) {
throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE);
}
$file_buffer = $this->encodeString($file_buffer, $encoding);
return $file_buffer;
} catch (Exception $exc) {
$this->setError($exc->getMessage());
$this->edebug($exc->getMessage());
if ($this->exceptions) {
throw $exc;
}
return '';
}
}
/**
* Encode a string in requested format.
* Returns an empty string on failure.
*
* @param string $str The text to encode
* @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
*
* @throws Exception
*
* @return string
*/
public function encodeString($str, $encoding = self::ENCODING_BASE64)
{
$encoded = '';
switch (strtolower($encoding)) {
case static::ENCODING_BASE64:
$encoded = chunk_split(
base64_encode($str),
static::STD_LINE_LENGTH,
static::$LE
);
break;
case static::ENCODING_7BIT:
case static::ENCODING_8BIT:
$encoded = static::normalizeBreaks($str);
//Make sure it ends with a line break
if (substr($encoded, -(strlen(static::$LE))) !== static::$LE) {
$encoded .= static::$LE;
}
break;
case static::ENCODING_BINARY:
$encoded = $str;
break;
case static::ENCODING_QUOTED_PRINTABLE:
$encoded = $this->encodeQP($str);
break;
default:
$this->setError($this->lang('encoding') . $encoding);
if ($this->exceptions) {
throw new Exception($this->lang('encoding') . $encoding);
}
break;
}
return $encoded;
}
/**
* Encode a header value (not including its label) optimally.
* Picks shortest of Q, B, or none. Result includes folding if needed.
* See RFC822 definitions for phrase, comment and text positions,
* and RFC2047 for inline encodings.
*
* @param string $str The header value to encode
* @param string $position What context the string will be used in
*
* @return string
*/
public function encodeHeader($str, $position = 'text')
{
$position = strtolower($position);
if ($this->UseSMTPUTF8 && !("comment" === $position)) {
return trim(static::normalizeBreaks($str));
}
$matchcount = 0;
switch (strtolower($position)) {
case 'phrase':
if (!preg_match('/[\200-\377]/', $str)) {
//Can't use addslashes as we don't know the value of magic_quotes_sybase
$encoded = addcslashes($str, "\0..\37\177\\\"");
if (($str === $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
return $encoded;
}
return "\"$encoded\"";
}
$matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
break;
/* @noinspection PhpMissingBreakStatementInspection */
case 'comment':
$matchcount = preg_match_all('/[()"]/', $str, $matches);
//fallthrough
case 'text':
default:
$matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
break;
}
if ($this->has8bitChars($str)) {
$charset = $this->CharSet;
} else {
$charset = static::CHARSET_ASCII;
}
//Q/B encoding adds 8 chars and the charset ("` =?<charset>?[QB]?<content>?=`").
$overhead = 8 + strlen($charset);
if ('mail' === $this->Mailer) {
$maxlen = static::MAIL_MAX_LINE_LENGTH - $overhead;
} else {
$maxlen = static::MAX_LINE_LENGTH - $overhead;
}
//Select the encoding that produces the shortest output and/or prevents corruption.
if ($matchcount > strlen($str) / 3) {
//More than 1/3 of the content needs encoding, use B-encode.
$encoding = 'B';
} elseif ($matchcount > 0) {
//Less than 1/3 of the content needs encoding, use Q-encode.
$encoding = 'Q';
} elseif (strlen($str) > $maxlen) {
//No encoding needed, but value exceeds max line length, use Q-encode to prevent corruption.
$encoding = 'Q';
} else {
//No reformatting needed
$encoding = false;
}
switch ($encoding) {
case 'B':
if ($this->hasMultiBytes($str)) {
//Use a custom function which correctly encodes and wraps long
//multibyte strings without breaking lines within a character
$encoded = $this->base64EncodeWrapMB($str, "\n");
} else {
$encoded = base64_encode($str);
$maxlen -= $maxlen % 4;
$encoded = trim(chunk_split($encoded, $maxlen, "\n"));
}
$encoded = preg_replace('/^(.*)$/m', ' =?' . $charset . "?$encoding?\\1?=", $encoded);
break;
case 'Q':
$encoded = $this->encodeQ($str, $position);
$encoded = $this->wrapText($encoded, $maxlen, true);
$encoded = str_replace('=' . static::$LE, "\n", trim($encoded));
$encoded = preg_replace('/^(.*)$/m', ' =?' . $charset . "?$encoding?\\1?=", $encoded);
break;
default:
return $str;
}
return trim(static::normalizeBreaks($encoded));
}
/**
* Check if a string contains multi-byte characters.
*
* @param string $str multi-byte text to wrap encode
*
* @return bool
*/
public function hasMultiBytes($str)
{
if (function_exists('mb_strlen')) {
return strlen($str) > mb_strlen($str, $this->CharSet);
}
//Assume no multibytes (we can't handle without mbstring functions anyway)
return false;
}
/**
* Does a string contain any 8-bit chars (in any charset)?
*
* @param string $text
*
* @return bool
*/
public function has8bitChars($text)
{
return (bool) preg_match('/[\x80-\xFF]/', $text);
}
/**
* Encode and wrap long multibyte strings for mail headers
* without breaking lines within a character.
* Adapted from a function by paravoid.
*
* @see https://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283
*
* @param string $str multi-byte text to wrap encode
* @param string $linebreak string to use as linefeed/end-of-line
*
* @return string
*/
public function base64EncodeWrapMB($str, $linebreak = null)
{
$start = '=?' . $this->CharSet . '?B?';
$end = '?=';
$encoded = '';
if (null === $linebreak) {
$linebreak = static::$LE;
}
$mb_length = mb_strlen($str, $this->CharSet);
//Each line must have length <= 75, including $start and $end
$length = 75 - strlen($start) - strlen($end);
//Average multi-byte ratio
$ratio = $mb_length / strlen($str);
//Base64 has a 4:3 ratio
$avgLength = floor($length * $ratio * .75);
$offset = 0;
for ($i = 0; $i < $mb_length; $i += $offset) {
$lookBack = 0;
do {
$offset = $avgLength - $lookBack;
$chunk = mb_substr($str, $i, $offset, $this->CharSet);
$chunk = base64_encode($chunk);
++$lookBack;
} while (strlen($chunk) > $length);
$encoded .= $chunk . $linebreak;
}
//Chomp the last linefeed
return substr($encoded, 0, -strlen($linebreak));
}
/**
* Encode a string in quoted-printable format.
* According to RFC2045 section 6.7.
*
* @param string $string The text to encode
*
* @return string
*/
public function encodeQP($string)
{
return static::normalizeBreaks(quoted_printable_encode($string));
}
/**
* Encode a string using Q encoding.
*
* @see https://www.rfc-editor.org/rfc/rfc2047#section-4.2
*
* @param string $str the text to encode
* @param string $position Where the text is going to be used, see the RFC for what that means
*
* @return string
*/
public function encodeQ($str, $position = 'text')
{
//There should not be any EOL in the string
$pattern = '';
$encoded = str_replace(["\r", "\n"], '', $str);
switch (strtolower($position)) {
case 'phrase':
//RFC 2047 section 5.3
$pattern = '^A-Za-z0-9!*+\/ -';
break;
/*
* RFC 2047 section 5.2.
* Build $pattern without including delimiters and []
*/
/* @noinspection PhpMissingBreakStatementInspection */
case 'comment':
$pattern = '\(\)"';
/* Intentional fall through */
case 'text':
default:
//RFC 2047 section 5.1
//Replace every high ascii, control, =, ? and _ characters
$pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
break;
}
$matches = [];
if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
//If the string contains an '=', make sure it's the first thing we replace
//so as to avoid double-encoding
$eqkey = array_search('=', $matches[0], true);
if (false !== $eqkey) {
unset($matches[0][$eqkey]);
array_unshift($matches[0], '=');
}
foreach (array_unique($matches[0]) as $char) {
$encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);
}
}
//Replace spaces with _ (more readable than =20)
//RFC 2047 section 4.2(2)
return str_replace(' ', '_', $encoded);
}
/**
* Add a string or binary attachment (non-filesystem).
* This method can be used to attach ascii or binary data,
* such as a BLOB record from a database.
*
* @param string $string String attachment data
* @param string $filename Name of the attachment
* @param string $encoding File encoding (see $Encoding)
* @param string $type File extension (MIME) type
* @param string $disposition Disposition to use
*
* @throws Exception
*
* @return bool True on successfully adding an attachment
*/
public function addStringAttachment(
$string,
$filename,
$encoding = self::ENCODING_BASE64,
$type = '',
$disposition = 'attachment'
) {
try {
//If a MIME type is not specified, try to work it out from the file name
if ('' === $type) {
$type = static::filenameToType($filename);
}
if (!$this->validateEncoding($encoding)) {
throw new Exception($this->lang('encoding') . $encoding);
}
//Append to $attachment array
$this->attachment[] = [
0 => $string,
1 => $filename,
2 => static::mb_pathinfo($filename, PATHINFO_BASENAME),
3 => $encoding,
4 => $type,
5 => true, //isStringAttachment
6 => $disposition,
7 => 0,
];
} catch (Exception $exc) {
$this->setError($exc->getMessage());
$this->edebug($exc->getMessage());
if ($this->exceptions) {
throw $exc;
}
return false;
}
return true;
}
/**
* Add an embedded (inline) attachment from a file.
* This can include images, sounds, and just about any other document type.
* These differ from 'regular' attachments in that they are intended to be
* displayed inline with the message, not just attached for download.
* This is used in HTML messages that embed the images
* the HTML refers to using the `$cid` value in `img` tags, for example `<img src="cid:mylogo">`.
* Never use a user-supplied path to a file!
*
* @param string $path Path to the attachment
* @param string $cid Content ID of the attachment; Use this to reference
* the content when using an embedded image in HTML
* @param string $name Overrides the attachment filename
* @param string $encoding File encoding (see $Encoding) defaults to `base64`
* @param string $type File MIME type (by default mapped from the `$path` filename's extension)
* @param string $disposition Disposition to use: `inline` (default) or `attachment`
* (unlikely you want this {@see `addAttachment()`} instead)
*
* @return bool True on successfully adding an attachment
* @throws Exception
*
*/
public function addEmbeddedImage(
$path,
$cid,
$name = '',
$encoding = self::ENCODING_BASE64,
$type = '',
$disposition = 'inline'
) {
try {
if (!static::fileIsAccessible($path)) {
throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
}
//If a MIME type is not specified, try to work it out from the file name
if ('' === $type) {
$type = static::filenameToType($path);
}
if (!$this->validateEncoding($encoding)) {
throw new Exception($this->lang('encoding') . $encoding);
}
$filename = (string) static::mb_pathinfo($path, PATHINFO_BASENAME);
if ('' === $name) {
$name = $filename;
}
//Append to $attachment array
$this->attachment[] = [
0 => $path,
1 => $filename,
2 => $name,
3 => $encoding,
4 => $type,
5 => false, //isStringAttachment
6 => $disposition,
7 => $cid,
];
} catch (Exception $exc) {
$this->setError($exc->getMessage());
$this->edebug($exc->getMessage());
if ($this->exceptions) {
throw $exc;
}
return false;
}
return true;
}
/**
* Add an embedded stringified attachment.
* This can include images, sounds, and just about any other document type.
* If your filename doesn't contain an extension, be sure to set the $type to an appropriate MIME type.
*
* @param string $string The attachment binary data
* @param string $cid Content ID of the attachment; Use this to reference
* the content when using an embedded image in HTML
* @param string $name A filename for the attachment. If this contains an extension,
* PHPMailer will attempt to set a MIME type for the attachment.
* For example 'file.jpg' would get an 'image/jpeg' MIME type.
* @param string $encoding File encoding (see $Encoding), defaults to 'base64'
* @param string $type MIME type - will be used in preference to any automatically derived type
* @param string $disposition Disposition to use
*
* @throws Exception
*
* @return bool True on successfully adding an attachment
*/
public function addStringEmbeddedImage(
$string,
$cid,
$name = '',
$encoding = self::ENCODING_BASE64,
$type = '',
$disposition = 'inline'
) {
try {
//If a MIME type is not specified, try to work it out from the name
if ('' === $type && !empty($name)) {
$type = static::filenameToType($name);
}
if (!$this->validateEncoding($encoding)) {
throw new Exception($this->lang('encoding') . $encoding);
}
//Append to $attachment array
$this->attachment[] = [
0 => $string,
1 => $name,
2 => $name,
3 => $encoding,
4 => $type,
5 => true, //isStringAttachment
6 => $disposition,
7 => $cid,
];
} catch (Exception $exc) {
$this->setError($exc->getMessage());
$this->edebug($exc->getMessage());
if ($this->exceptions) {
throw $exc;
}
return false;
}
return true;
}
/**
* Validate encodings.
*
* @param string $encoding
*
* @return bool
*/
protected function validateEncoding($encoding)
{
return in_array(
$encoding,
[
self::ENCODING_7BIT,
self::ENCODING_QUOTED_PRINTABLE,
self::ENCODING_BASE64,
self::ENCODING_8BIT,
self::ENCODING_BINARY,
],
true
);
}
/**
* Check if an embedded attachment is present with this cid.
*
* @param string $cid
*
* @return bool
*/
protected function cidExists($cid)
{
foreach ($this->attachment as $attachment) {
if ('inline' === $attachment[6] && $cid === $attachment[7]) {
return true;
}
}
return false;
}
/**
* Check if an inline attachment is present.
*
* @return bool
*/
public function inlineImageExists()
{
foreach ($this->attachment as $attachment) {
if ('inline' === $attachment[6]) {
return true;
}
}
return false;
}
/**
* Check if an attachment (non-inline) is present.
*
* @return bool
*/
public function attachmentExists()
{
foreach ($this->attachment as $attachment) {
if ('attachment' === $attachment[6]) {
return true;
}
}
return false;
}
/**
* Check if this message has an alternative body set.
*
* @return bool
*/
public function alternativeExists()
{
return !empty($this->AltBody);
}
/**
* Clear queued addresses of given kind.
*
* @param string $kind 'to', 'cc', or 'bcc'
*/
public function clearQueuedAddresses($kind)
{
$this->RecipientsQueue = array_filter(
$this->RecipientsQueue,
static function ($params) use ($kind) {
return $params[0] !== $kind;
}
);
}
/**
* Clear all To recipients.
*/
public function clearAddresses()
{
foreach ($this->to as $to) {
unset($this->all_recipients[strtolower($to[0])]);
}
$this->to = [];
$this->clearQueuedAddresses('to');
}
/**
* Clear all CC recipients.
*/
public function clearCCs()
{
foreach ($this->cc as $cc) {
unset($this->all_recipients[strtolower($cc[0])]);
}
$this->cc = [];
$this->clearQueuedAddresses('cc');
}
/**
* Clear all BCC recipients.
*/
public function clearBCCs()
{
foreach ($this->bcc as $bcc) {
unset($this->all_recipients[strtolower($bcc[0])]);
}
$this->bcc = [];
$this->clearQueuedAddresses('bcc');
}
/**
* Clear all ReplyTo recipients.
*/
public function clearReplyTos()
{
$this->ReplyTo = [];
$this->ReplyToQueue = [];
}
/**
* Clear all recipient types.
*/
public function clearAllRecipients()
{
$this->to = [];
$this->cc = [];
$this->bcc = [];
$this->all_recipients = [];
$this->RecipientsQueue = [];
}
/**
* Clear all filesystem, string, and binary attachments.
*/
public function clearAttachments()
{
$this->attachment = [];
}
/**
* Clear all custom headers.
*/
public function clearCustomHeaders()
{
$this->CustomHeader = [];
}
/**
* Clear a specific custom header by name or name and value.
* $name value can be overloaded to contain
* both header name and value (name:value).
*
* @param string $name Custom header name
* @param string|null $value Header value
*
* @return bool True if a header was replaced successfully
*/
public function clearCustomHeader($name, $value = null)
{
if (null === $value && strpos($name, ':') !== false) {
//Value passed in as name:value
list($name, $value) = explode(':', $name, 2);
}
$name = trim($name);
$value = (null === $value) ? null : trim($value);
foreach ($this->CustomHeader as $k => $pair) {
if ($pair[0] == $name) {
// We remove the header if the value is not provided or it matches.
if (null === $value || $pair[1] == $value) {
unset($this->CustomHeader[$k]);
}
}
}
return true;
}
/**
* Replace a custom header.
* $name value can be overloaded to contain
* both header name and value (name:value).
*
* @param string $name Custom header name
* @param string|null $value Header value
*
* @return bool True if a header was replaced successfully
* @throws Exception
*/
public function replaceCustomHeader($name, $value = null)
{
if (null === $value && strpos($name, ':') !== false) {
//Value passed in as name:value
list($name, $value) = explode(':', $name, 2);
}
$name = trim($name);
$value = (null === $value) ? '' : trim($value);
$replaced = false;
foreach ($this->CustomHeader as $k => $pair) {
if ($pair[0] == $name) {
if ($replaced) {
unset($this->CustomHeader[$k]);
continue;
}
if (strpbrk($name . $value, "\r\n") !== false) {
if ($this->exceptions) {
throw new Exception($this->lang('invalid_header'));
}
return false;
}
$this->CustomHeader[$k] = [$name, $value];
$replaced = true;
}
}
return true;
}
/**
* Add an error message to the error container.
*
* @param string $msg
*/
protected function setError($msg)
{
++$this->error_count;
if ('smtp' === $this->Mailer && null !== $this->smtp) {
$lasterror = $this->smtp->getError();
if (!empty($lasterror['error'])) {
$msg .= ' ' . $this->lang('smtp_error') . $lasterror['error'];
if (!empty($lasterror['detail'])) {
$msg .= ' ' . $this->lang('smtp_detail') . $lasterror['detail'];
}
if (!empty($lasterror['smtp_code'])) {
$msg .= ' ' . $this->lang('smtp_code') . $lasterror['smtp_code'];
}
if (!empty($lasterror['smtp_code_ex'])) {
$msg .= ' ' . $this->lang('smtp_code_ex') . $lasterror['smtp_code_ex'];
}
}
}
$this->ErrorInfo = $msg;
}
/**
* Return an RFC 822 formatted date.
*
* @return string
*/
public static function rfcDate()
{
//Set the time zone to whatever the default is to avoid 500 errors
//Will default to UTC if it's not set properly in php.ini
date_default_timezone_set(@date_default_timezone_get());
return date('D, j M Y H:i:s O');
}
/**
* Get the server hostname.
* Returns 'localhost.localdomain' if unknown.
*
* @return string
*/
protected function serverHostname()
{
$result = '';
if (!empty($this->Hostname)) {
$result = $this->Hostname;
} elseif (isset($_SERVER) && array_key_exists('SERVER_NAME', $_SERVER)) {
$result = $_SERVER['SERVER_NAME'];
} elseif (function_exists('gethostname') && gethostname() !== false) {
$result = gethostname();
} elseif (php_uname('n') !== '') {
$result = php_uname('n');
}
if (!static::isValidHost($result)) {
return 'localhost.localdomain';
}
return $result;
}
/**
* Validate whether a string contains a valid value to use as a hostname or IP address.
* IPv6 addresses must include [], e.g. `[::1]`, not just `::1`.
*
* @param string $host The host name or IP address to check
*
* @return bool
*/
public static function isValidHost($host)
{
//Simple syntax limits
if (
empty($host)
|| !is_string($host)
|| strlen($host) > 256
|| !preg_match('/^([a-z\d.-]*|\[[a-f\d:]+\])$/i', $host)
) {
return false;
}
//Looks like a bracketed IPv6 address
if (strlen($host) > 2 && substr($host, 0, 1) === '[' && substr($host, -1, 1) === ']') {
return filter_var(substr($host, 1, -1), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false;
}
//If removing all the dots results in a numeric string, it must be an IPv4 address.
//Need to check this first because otherwise things like `999.0.0.0` are considered valid host names
if (is_numeric(str_replace('.', '', $host))) {
//Is it a valid IPv4 address?
return filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false;
}
//Is it a syntactically valid hostname (when embedded in a URL)?
return filter_var('https://' . $host, FILTER_VALIDATE_URL) !== false;
}
/**
* Check whether the supplied address uses Unicode in the local part.
*
* @return bool
*/
protected function addressHasUnicodeLocalPart($address)
{
return (bool) preg_match('/[\x80-\xFF].*@/', $address);
}
/**
* Check whether any of the supplied addresses use Unicode in the local part.
*
* @return bool
*/
protected function anyAddressHasUnicodeLocalPart($addresses)
{
foreach ($addresses as $address) {
if (is_array($address)) {
$address = $address[0];
}
if ($this->addressHasUnicodeLocalPart($address)) {
return true;
}
}
return false;
}
/**
* Check whether the message requires SMTPUTF8 based on what's known so far.
*
* @return bool
*/
public function needsSMTPUTF8()
{
return $this->UseSMTPUTF8;
}
/**
* Get an error message in the current language.
*
* @param string $key
*
* @return string
*/
protected function lang($key)
{
if (count($this->language) < 1) {
$this->setLanguage(); //Set the default language
}
if (array_key_exists($key, $this->language)) {
if ('smtp_connect_failed' === $key) {
//Include a link to troubleshooting docs on SMTP connection failure.
//This is by far the biggest cause of support questions
//but it's usually not PHPMailer's fault.
return $this->language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting';
}
return $this->language[$key];
}
//Return the key as a fallback
return $key;
}
/**
* Build an error message starting with a generic one and adding details if possible.
*
* @param string $base_key
* @return string
*/
private function getSmtpErrorMessage($base_key)
{
$message = $this->lang($base_key);
$error = $this->smtp->getError();
if (!empty($error['error'])) {
$message .= ' ' . $error['error'];
if (!empty($error['detail'])) {
$message .= ' ' . $error['detail'];
}
}
return $message;
}
/**
* Check if an error occurred.
*
* @return bool True if an error did occur
*/
public function isError()
{
return $this->error_count > 0;
}
/**
* Add a custom header.
* $name value can be overloaded to contain
* both header name and value (name:value).
*
* @param string $name Custom header name
* @param string|null $value Header value
*
* @return bool True if a header was set successfully
* @throws Exception
*/
public function addCustomHeader($name, $value = null)
{
if (null === $value && strpos($name, ':') !== false) {
//Value passed in as name:value
list($name, $value) = explode(':', $name, 2);
}
$name = trim($name);
$value = (null === $value) ? '' : trim($value);
//Ensure name is not empty, and that neither name nor value contain line breaks
if (empty($name) || strpbrk($name . $value, "\r\n") !== false) {
if ($this->exceptions) {
throw new Exception($this->lang('invalid_header'));
}
return false;
}
$this->CustomHeader[] = [$name, $value];
return true;
}
/**
* Returns all custom headers.
*
* @return array
*/
public function getCustomHeaders()
{
return $this->CustomHeader;
}
/**
* Create a message body from an HTML string.
* Automatically inlines images and creates a plain-text version by converting the HTML,
* overwriting any existing values in Body and AltBody.
* Do not source $message content from user input!
* $basedir is prepended when handling relative URLs, e.g. <img src="/images/a.png"> and must not be empty
* will look for an image file in $basedir/images/a.png and convert it to inline.
* If you don't provide a $basedir, relative paths will be left untouched (and thus probably break in email)
* Converts data-uri images into embedded attachments.
* If you don't want to apply these transformations to your HTML, just set Body and AltBody directly.
*
* @param string $message HTML message string
* @param string $basedir Absolute path to a base directory to prepend to relative paths to images
* @param bool|callable $advanced Whether to use the internal HTML to text converter
* or your own custom converter
* @return string The transformed message body
*
* @throws Exception
*
* @see PHPMailer::html2text()
*/
public function msgHTML($message, $basedir = '', $advanced = false)
{
preg_match_all('/(?<!-)(src|background)=["\'](.*)["\']/Ui', $message, $images);
if (array_key_exists(2, $images)) {
if (strlen($basedir) > 1 && '/' !== substr($basedir, -1)) {
//Ensure $basedir has a trailing /
$basedir .= '/';
}
foreach ($images[2] as $imgindex => $url) {
//Convert data URIs into embedded images
//e.g. "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
$match = [];
if (preg_match('#^data:(image/(?:jpe?g|gif|png));?(base64)?,(.+)#', $url, $match)) {
if (count($match) === 4 && static::ENCODING_BASE64 === $match[2]) {
$data = base64_decode($match[3]);
} elseif ('' === $match[2]) {
$data = rawurldecode($match[3]);
} else {
//Not recognised so leave it alone
continue;
}
//Hash the decoded data, not the URL, so that the same data-URI image used in multiple places
//will only be embedded once, even if it used a different encoding
$cid = substr(hash('sha256', $data), 0, 32) . '@phpmailer.0'; //RFC2392 S 2
if (!$this->cidExists($cid)) {
$this->addStringEmbeddedImage(
$data,
$cid,
'embed' . $imgindex,
static::ENCODING_BASE64,
$match[1]
);
}
$message = str_replace(
$images[0][$imgindex],
$images[1][$imgindex] . '="cid:' . $cid . '"',
$message
);
continue;
}
if (
//Only process relative URLs if a basedir is provided (i.e. no absolute local paths)
!empty($basedir)
//Ignore URLs containing parent dir traversal (..)
&& (strpos($url, '..') === false)
//Do not change urls that are already inline images
&& 0 !== strpos($url, 'cid:')
//Do not change absolute URLs, including anonymous protocol
&& !preg_match('#^[a-z][a-z0-9+.-]*:?//#i', $url)
) {
$filename = static::mb_pathinfo($url, PATHINFO_BASENAME);
$directory = dirname($url);
if ('.' === $directory) {
$directory = '';
}
//RFC2392 S 2
$cid = substr(hash('sha256', $url), 0, 32) . '@phpmailer.0';
if (strlen($basedir) > 1 && '/' !== substr($basedir, -1)) {
$basedir .= '/';
}
if (strlen($directory) > 1 && '/' !== substr($directory, -1)) {
$directory .= '/';
}
if (
$this->addEmbeddedImage(
$basedir . $directory . $filename,
$cid,
$filename,
static::ENCODING_BASE64,
static::_mime_types((string) static::mb_pathinfo($filename, PATHINFO_EXTENSION))
)
) {
$message = preg_replace(
'/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui',
$images[1][$imgindex] . '="cid:' . $cid . '"',
$message
);
}
}
}
}
$this->isHTML();
//Convert all message body line breaks to LE, makes quoted-printable encoding work much better
$this->Body = static::normalizeBreaks($message);
$this->AltBody = static::normalizeBreaks($this->html2text($message, $advanced));
if (!$this->alternativeExists()) {
$this->AltBody = 'This is an HTML-only message. To view it, activate HTML in your email application.'
. static::$LE;
}
return $this->Body;
}
/**
* Convert an HTML string into plain text.
* This is used by msgHTML().
* Note - older versions of this function used a bundled advanced converter
* which was removed for license reasons in #232.
* Example usage:
*
* ```php
* //Use default conversion
* $plain = $mail->html2text($html);
* //Use your own custom converter
* $plain = $mail->html2text($html, function($html) {
* $converter = new MyHtml2text($html);
* return $converter->get_text();
* });
* ```
*
* @param string $html The HTML text to convert
* @param bool|callable $advanced Any boolean value to use the internal converter,
* or provide your own callable for custom conversion.
* *Never* pass user-supplied data into this parameter
*
* @return string
*/
public function html2text($html, $advanced = false)
{
if (is_callable($advanced)) {
return call_user_func($advanced, $html);
}
return html_entity_decode(
trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))),
ENT_QUOTES,
$this->CharSet
);
}
/**
* Get the MIME type for a file extension.
*
* @param string $ext File extension
*
* @return string MIME type of file
*/
public static function _mime_types($ext = '')
{
$mimes = [
'xl' => 'application/excel',
'js' => 'application/javascript',
'hqx' => 'application/mac-binhex40',
'cpt' => 'application/mac-compactpro',
'bin' => 'application/macbinary',
'doc' => 'application/msword',
'word' => 'application/msword',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
'class' => 'application/octet-stream',
'dll' => 'application/octet-stream',
'dms' => 'application/octet-stream',
'exe' => 'application/octet-stream',
'lha' => 'application/octet-stream',
'lzh' => 'application/octet-stream',
'psd' => 'application/octet-stream',
'sea' => 'application/octet-stream',
'so' => 'application/octet-stream',
'oda' => 'application/oda',
'pdf' => 'application/pdf',
'ai' => 'application/postscript',
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'smi' => 'application/smil',
'smil' => 'application/smil',
'mif' => 'application/vnd.mif',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'wbxml' => 'application/vnd.wap.wbxml',
'wmlc' => 'application/vnd.wap.wmlc',
'dcr' => 'application/x-director',
'dir' => 'application/x-director',
'dxr' => 'application/x-director',
'dvi' => 'application/x-dvi',
'gtar' => 'application/x-gtar',
'php3' => 'application/x-httpd-php',
'php4' => 'application/x-httpd-php',
'php' => 'application/x-httpd-php',
'phtml' => 'application/x-httpd-php',
'phps' => 'application/x-httpd-php-source',
'swf' => 'application/x-shockwave-flash',
'sit' => 'application/x-stuffit',
'tar' => 'application/x-tar',
'tgz' => 'application/x-tar',
'xht' => 'application/xhtml+xml',
'xhtml' => 'application/xhtml+xml',
'zip' => 'application/zip',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mp2' => 'audio/mpeg',
'mp3' => 'audio/mpeg',
'm4a' => 'audio/mp4',
'mpga' => 'audio/mpeg',
'aif' => 'audio/x-aiff',
'aifc' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'ram' => 'audio/x-pn-realaudio',
'rm' => 'audio/x-pn-realaudio',
'rpm' => 'audio/x-pn-realaudio-plugin',
'ra' => 'audio/x-realaudio',
'wav' => 'audio/x-wav',
'mka' => 'audio/x-matroska',
'bmp' => 'image/bmp',
'gif' => 'image/gif',
'jpeg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'jpg' => 'image/jpeg',
'png' => 'image/png',
'tiff' => 'image/tiff',
'tif' => 'image/tiff',
'webp' => 'image/webp',
'avif' => 'image/avif',
'heif' => 'image/heif',
'heifs' => 'image/heif-sequence',
'heic' => 'image/heic',
'heics' => 'image/heic-sequence',
'eml' => 'message/rfc822',
'css' => 'text/css',
'html' => 'text/html',
'htm' => 'text/html',
'shtml' => 'text/html',
'log' => 'text/plain',
'text' => 'text/plain',
'txt' => 'text/plain',
'rtx' => 'text/richtext',
'rtf' => 'text/rtf',
'vcf' => 'text/vcard',
'vcard' => 'text/vcard',
'ics' => 'text/calendar',
'xml' => 'text/xml',
'xsl' => 'text/xml',
'csv' => 'text/csv',
'wmv' => 'video/x-ms-wmv',
'mpeg' => 'video/mpeg',
'mpe' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mp4' => 'video/mp4',
'm4v' => 'video/mp4',
'mov' => 'video/quicktime',
'qt' => 'video/quicktime',
'rv' => 'video/vnd.rn-realvideo',
'avi' => 'video/x-msvideo',
'movie' => 'video/x-sgi-movie',
'webm' => 'video/webm',
'mkv' => 'video/x-matroska',
];
$ext = strtolower($ext);
if (array_key_exists($ext, $mimes)) {
return $mimes[$ext];
}
return 'application/octet-stream';
}
/**
* Map a file name to a MIME type.
* Defaults to 'application/octet-stream', i.e.. arbitrary binary data.
*
* @param string $filename A file name or full path, does not need to exist as a file
*
* @return string
*/
public static function filenameToType($filename)
{
//In case the path is a URL, strip any query string before getting extension
$qpos = strpos($filename, '?');
if (false !== $qpos) {
$filename = substr($filename, 0, $qpos);
}
$ext = static::mb_pathinfo($filename, PATHINFO_EXTENSION);
return static::_mime_types($ext);
}
/**
* Multi-byte-safe pathinfo replacement.
* Drop-in replacement for pathinfo(), but multibyte- and cross-platform-safe.
*
* @see https://www.php.net/manual/en/function.pathinfo.php#107461
*
* @param string $path A filename or path, does not need to exist as a file
* @param int|string $options Either a PATHINFO_* constant,
* or a string name to return only the specified piece
*
* @return string|array
*/
public static function mb_pathinfo($path, $options = null)
{
$ret = ['dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''];
$pathinfo = [];
if (preg_match('#^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^.\\\\/]+?)|))[\\\\/.]*$#m', $path, $pathinfo)) {
if (array_key_exists(1, $pathinfo)) {
$ret['dirname'] = $pathinfo[1];
}
if (array_key_exists(2, $pathinfo)) {
$ret['basename'] = $pathinfo[2];
}
if (array_key_exists(5, $pathinfo)) {
$ret['extension'] = $pathinfo[5];
}
if (array_key_exists(3, $pathinfo)) {
$ret['filename'] = $pathinfo[3];
}
}
switch ($options) {
case PATHINFO_DIRNAME:
case 'dirname':
return $ret['dirname'];
case PATHINFO_BASENAME:
case 'basename':
return $ret['basename'];
case PATHINFO_EXTENSION:
case 'extension':
return $ret['extension'];
case PATHINFO_FILENAME:
case 'filename':
return $ret['filename'];
default:
return $ret;
}
}
/**
* Set or reset instance properties.
* You should avoid this function - it's more verbose, less efficient, more error-prone and
* harder to debug than setting properties directly.
* Usage Example:
* `$mail->set('SMTPSecure', static::ENCRYPTION_STARTTLS);`
* is the same as:
* `$mail->SMTPSecure = static::ENCRYPTION_STARTTLS;`.
*
* @param string $name The property name to set
* @param mixed $value The value to set the property to
*
* @return bool
*/
public function set($name, $value = '')
{
if (property_exists($this, $name)) {
$this->{$name} = $value;
return true;
}
$this->setError($this->lang('variable_set') . $name);
return false;
}
/**
* Strip newlines to prevent header injection.
*
* @param string $str
*
* @return string
*/
public function secureHeader($str)
{
return trim(str_replace(["\r", "\n"], '', $str));
}
/**
* Normalize line breaks in a string.
* Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format.
* Defaults to CRLF (for message bodies) and preserves consecutive breaks.
*
* @param string $text
* @param string $breaktype What kind of line break to use; defaults to static::$LE
*
* @return string
*/
public static function normalizeBreaks($text, $breaktype = null)
{
if (null === $breaktype) {
$breaktype = static::$LE;
}
//Normalise to \n
$text = str_replace([self::CRLF, "\r"], "\n", $text);
//Now convert LE as needed
if ("\n" !== $breaktype) {
$text = str_replace("\n", $breaktype, $text);
}
return $text;
}
/**
* Remove trailing whitespace from a string.
*
* @param string $text
*
* @return string The text to remove whitespace from
*/
public static function stripTrailingWSP($text)
{
return rtrim($text, " \r\n\t");
}
/**
* Strip trailing line breaks from a string.
*
* @param string $text
*
* @return string The text to remove breaks from
*/
public static function stripTrailingBreaks($text)
{
return rtrim($text, "\r\n");
}
/**
* Return the current line break format string.
*
* @return string
*/
public static function getLE()
{
return static::$LE;
}
/**
* Set the line break format string, e.g. "\r\n".
*
* @param string $le
*/
protected static function setLE($le)
{
static::$LE = $le;
}
/**
* Set the public and private key files and password for S/MIME signing.
*
* @param string $cert_filename
* @param string $key_filename
* @param string $key_pass Password for private key
* @param string $extracerts_filename Optional path to chain certificate
*/
public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '')
{
$this->sign_cert_file = $cert_filename;
$this->sign_key_file = $key_filename;
$this->sign_key_pass = $key_pass;
$this->sign_extracerts_file = $extracerts_filename;
}
/**
* Quoted-Printable-encode a DKIM header.
*
* @param string $txt
*
* @return string
*/
public function DKIM_QP($txt)
{
$line = '';
$len = strlen($txt);
for ($i = 0; $i < $len; ++$i) {
$ord = ord($txt[$i]);
if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord === 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) {
$line .= $txt[$i];
} else {
$line .= '=' . sprintf('%02X', $ord);
}
}
return $line;
}
/**
* Generate a DKIM signature.
*
* @param string $signHeader
*
* @throws Exception
*
* @return string The DKIM signature value
*/
public function DKIM_Sign($signHeader)
{
if (!defined('PKCS7_TEXT')) {
if ($this->exceptions) {
throw new Exception($this->lang('extension_missing') . 'openssl');
}
return '';
}
$privKeyStr = !empty($this->DKIM_private_string) ?
$this->DKIM_private_string :
file_get_contents($this->DKIM_private);
if ('' !== $this->DKIM_passphrase) {
$privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
} else {
$privKey = openssl_pkey_get_private($privKeyStr);
}
if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) {
if (\PHP_MAJOR_VERSION < 8) {
openssl_pkey_free($privKey);
}
return base64_encode($signature);
}
if (\PHP_MAJOR_VERSION < 8) {
openssl_pkey_free($privKey);
}
return '';
}
/**
* Generate a DKIM canonicalization header.
* Uses the 'relaxed' algorithm from RFC6376 section 3.4.2.
* Canonicalized headers should *always* use CRLF, regardless of mailer setting.
*
* @see https://www.rfc-editor.org/rfc/rfc6376#section-3.4.2
*
* @param string $signHeader Header
*
* @return string
*/
public function DKIM_HeaderC($signHeader)
{
//Normalize breaks to CRLF (regardless of the mailer)
$signHeader = static::normalizeBreaks($signHeader, self::CRLF);
//Unfold header lines
//Note PCRE \s is too broad a definition of whitespace; RFC5322 defines it as `[ \t]`
//@see https://www.rfc-editor.org/rfc/rfc5322#section-2.2
//That means this may break if you do something daft like put vertical tabs in your headers.
$signHeader = preg_replace('/\r\n[ \t]+/', ' ', $signHeader);
//Break headers out into an array
$lines = explode(self::CRLF, $signHeader);
foreach ($lines as $key => $line) {
//If the header is missing a :, skip it as it's invalid
//This is likely to happen because the explode() above will also split
//on the trailing LE, leaving an empty line
if (strpos($line, ':') === false) {
continue;
}
list($heading, $value) = explode(':', $line, 2);
//Lower-case header name
$heading = strtolower($heading);
//Collapse white space within the value, also convert WSP to space
$value = preg_replace('/[ \t]+/', ' ', $value);
//RFC6376 is slightly unclear here - it says to delete space at the *end* of each value
//But then says to delete space before and after the colon.
//Net result is the same as trimming both ends of the value.
//By elimination, the same applies to the field name
$lines[$key] = trim($heading, " \t") . ':' . trim($value, " \t");
}
return implode(self::CRLF, $lines);
}
/**
* Generate a DKIM canonicalization body.
* Uses the 'simple' algorithm from RFC6376 section 3.4.3.
* Canonicalized bodies should *always* use CRLF, regardless of mailer setting.
*
* @see https://www.rfc-editor.org/rfc/rfc6376#section-3.4.3
*
* @param string $body Message Body
*
* @return string
*/
public function DKIM_BodyC($body)
{
if (empty($body)) {
return self::CRLF;
}
//Normalize line endings to CRLF
$body = static::normalizeBreaks($body, self::CRLF);
//Reduce multiple trailing line breaks to a single one
return static::stripTrailingBreaks($body) . self::CRLF;
}
/**
* Create the DKIM header and body in a new message header.
*
* @param string $headers_line Header lines
* @param string $subject Subject
* @param string $body Body
*
* @throws Exception
*
* @return string
*/
public function DKIM_Add($headers_line, $subject, $body)
{
$DKIMsignatureType = 'rsa-sha256'; //Signature & hash algorithms
$DKIMcanonicalization = 'relaxed/simple'; //Canonicalization methods of header & body
$DKIMquery = 'dns/txt'; //Query method
$DKIMtime = time();
//Always sign these headers without being asked
//Recommended list from https://www.rfc-editor.org/rfc/rfc6376#section-5.4.1
$autoSignHeaders = [
'from',
'to',
'cc',
'date',
'subject',
'reply-to',
'message-id',
'content-type',
'mime-version',
'x-mailer',
];
if (stripos($headers_line, 'Subject') === false) {
$headers_line .= 'Subject: ' . $subject . static::$LE;
}
$headerLines = explode(static::$LE, $headers_line);
$currentHeaderLabel = '';
$currentHeaderValue = '';
$parsedHeaders = [];
$headerLineIndex = 0;
$headerLineCount = count($headerLines);
foreach ($headerLines as $headerLine) {
$matches = [];
if (preg_match('/^([^ \t]*?)(?::[ \t]*)(.*)$/', $headerLine, $matches)) {
if ($currentHeaderLabel !== '') {
//We were previously in another header; This is the start of a new header, so save the previous one
$parsedHeaders[] = ['label' => $currentHeaderLabel, 'value' => $currentHeaderValue];
}
$currentHeaderLabel = $matches[1];
$currentHeaderValue = $matches[2];
} elseif (preg_match('/^[ \t]+(.*)$/', $headerLine, $matches)) {
//This is a folded continuation of the current header, so unfold it
$currentHeaderValue .= ' ' . $matches[1];
}
++$headerLineIndex;
if ($headerLineIndex >= $headerLineCount) {
//This was the last line, so finish off this header
$parsedHeaders[] = ['label' => $currentHeaderLabel, 'value' => $currentHeaderValue];
}
}
$copiedHeaders = [];
$headersToSignKeys = [];
$headersToSign = [];
foreach ($parsedHeaders as $header) {
//Is this header one that must be included in the DKIM signature?
if (in_array(strtolower($header['label']), $autoSignHeaders, true)) {
$headersToSignKeys[] = $header['label'];
$headersToSign[] = $header['label'] . ': ' . $header['value'];
if ($this->DKIM_copyHeaderFields) {
$copiedHeaders[] = $header['label'] . ':' . //Note no space after this, as per RFC
str_replace('|', '=7C', $this->DKIM_QP($header['value']));
}
continue;
}
//Is this an extra custom header we've been asked to sign?
if (in_array($header['label'], $this->DKIM_extraHeaders, true)) {
//Find its value in custom headers
foreach ($this->CustomHeader as $customHeader) {
if ($customHeader[0] === $header['label']) {
$headersToSignKeys[] = $header['label'];
$headersToSign[] = $header['label'] . ': ' . $header['value'];
if ($this->DKIM_copyHeaderFields) {
$copiedHeaders[] = $header['label'] . ':' . //Note no space after this, as per RFC
str_replace('|', '=7C', $this->DKIM_QP($header['value']));
}
//Skip straight to the next header
continue 2;
}
}
}
}
$copiedHeaderFields = '';
if ($this->DKIM_copyHeaderFields && count($copiedHeaders) > 0) {
//Assemble a DKIM 'z' tag
$copiedHeaderFields = ' z=';
$first = true;
foreach ($copiedHeaders as $copiedHeader) {
if (!$first) {
$copiedHeaderFields .= static::$LE . ' |';
}
//Fold long values
if (strlen($copiedHeader) > self::STD_LINE_LENGTH - 3) {
$copiedHeaderFields .= substr(
chunk_split($copiedHeader, self::STD_LINE_LENGTH - 3, static::$LE . self::FWS),
0,
-strlen(static::$LE . self::FWS)
);
} else {
$copiedHeaderFields .= $copiedHeader;
}
$first = false;
}
$copiedHeaderFields .= ';' . static::$LE;
}
$headerKeys = ' h=' . implode(':', $headersToSignKeys) . ';' . static::$LE;
$headerValues = implode(static::$LE, $headersToSign);
$body = $this->DKIM_BodyC($body);
//Base64 of packed binary SHA-256 hash of body
$DKIMb64 = base64_encode(pack('H*', hash('sha256', $body)));
$ident = '';
if ('' !== $this->DKIM_identity) {
$ident = ' i=' . $this->DKIM_identity . ';' . static::$LE;
}
//The DKIM-Signature header is included in the signature *except for* the value of the `b` tag
//which is appended after calculating the signature
//https://www.rfc-editor.org/rfc/rfc6376#section-3.5
$dkimSignatureHeader = 'DKIM-Signature: v=1;' .
' d=' . $this->DKIM_domain . ';' .
' s=' . $this->DKIM_selector . ';' . static::$LE .
' a=' . $DKIMsignatureType . ';' .
' q=' . $DKIMquery . ';' .
' t=' . $DKIMtime . ';' .
' c=' . $DKIMcanonicalization . ';' . static::$LE .
$headerKeys .
$ident .
$copiedHeaderFields .
' bh=' . $DKIMb64 . ';' . static::$LE .
' b=';
//Canonicalize the set of headers
$canonicalizedHeaders = $this->DKIM_HeaderC(
$headerValues . static::$LE . $dkimSignatureHeader
);
$signature = $this->DKIM_Sign($canonicalizedHeaders);
$signature = trim(chunk_split($signature, self::STD_LINE_LENGTH - 3, static::$LE . self::FWS));
return static::normalizeBreaks($dkimSignatureHeader . $signature);
}
/**
* Detect if a string contains a line longer than the maximum line length
* allowed by RFC 2822 section 2.1.1.
*
* @param string $str
*
* @return bool
*/
public static function hasLineLongerThanMax($str)
{
return (bool) preg_match('/^(.{' . (self::MAX_LINE_LENGTH + strlen(static::$LE)) . ',})/m', $str);
}
/**
* If a string contains any "special" characters, double-quote the name,
* and escape any double quotes with a backslash.
*
* @param string $str
*
* @return string
*
* @see RFC822 3.4.1
*/
public static function quotedString($str)
{
if (preg_match('/[ ()<>@,;:"\/\[\]?=]/', $str)) {
//If the string contains any of these chars, it must be double-quoted
//and any double quotes must be escaped with a backslash
return '"' . str_replace('"', '\\"', $str) . '"';
}
//Return the string untouched, it doesn't need quoting
return $str;
}
/**
* Allows for public read access to 'to' property.
* Before the send() call, queued addresses (i.e. with IDN) are not yet included.
*
* @return array
*/
public function getToAddresses()
{
return $this->to;
}
/**
* Allows for public read access to 'cc' property.
* Before the send() call, queued addresses (i.e. with IDN) are not yet included.
*
* @return array
*/
public function getCcAddresses()
{
return $this->cc;
}
/**
* Allows for public read access to 'bcc' property.
* Before the send() call, queued addresses (i.e. with IDN) are not yet included.
*
* @return array
*/
public function getBccAddresses()
{
return $this->bcc;
}
/**
* Allows for public read access to 'ReplyTo' property.
* Before the send() call, queued addresses (i.e. with IDN) are not yet included.
*
* @return array
*/
public function getReplyToAddresses()
{
return $this->ReplyTo;
}
/**
* Allows for public read access to 'all_recipients' property.
* Before the send() call, queued addresses (i.e. with IDN) are not yet included.
*
* @return array
*/
public function getAllRecipientAddresses()
{
return $this->all_recipients;
}
/**
* Perform a callback.
*
* @param bool $isSent
* @param array $to
* @param array $cc
* @param array $bcc
* @param string $subject
* @param string $body
* @param string $from
* @param array $extra
*/
protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from, $extra)
{
if (!empty($this->action_function) && is_callable($this->action_function)) {
call_user_func($this->action_function, $isSent, $to, $cc, $bcc, $subject, $body, $from, $extra);
}
}
/**
* Get the OAuthTokenProvider instance.
*
* @return OAuthTokenProvider
*/
public function getOAuth()
{
return $this->oauth;
}
/**
* Set an OAuthTokenProvider instance.
*/
public function setOAuth(OAuthTokenProvider $oauth)
{
$this->oauth = $oauth;
}
}
"""
"./api/phpmailer/src/POP3.php" :
"""
<?php
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2020 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
* 1) This class does not support APOP authentication.
* 2) Opening and closing lots of POP3 connections can be quite slow. If you need
* to send a batch of emails then just perform the authentication once at the start,
* and then loop through your mail sending script. Providing this process doesn't
* take longer than the verification period lasts on your POP3 server, you should be fine.
* 3) This is really ancient technology; you should only need to use it to talk to very old systems.
* 4) This POP3 class is deliberately lightweight and incomplete, implementing just
* enough to do authentication.
* If you want a more complete class there are other POP3 classes for PHP available.
*
* @author Richard Davey (original author) <rich@corephp.co.uk>
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
*/
class POP3
{
/**
* The POP3 PHPMailer Version number.
*
* @var string
*/
const VERSION = '6.10.0';
/**
* Default POP3 port number.
*
* @var int
*/
const DEFAULT_PORT = 110;
/**
* Default timeout in seconds.
*
* @var int
*/
const DEFAULT_TIMEOUT = 30;
/**
* POP3 class debug output mode.
* Debug output level.
* Options:
* @see POP3::DEBUG_OFF: No output
* @see POP3::DEBUG_SERVER: Server messages, connection/server errors
* @see POP3::DEBUG_CLIENT: Client and Server messages, connection/server errors
*
* @var int
*/
public $do_debug = self::DEBUG_OFF;
/**
* POP3 mail server hostname.
*
* @var string
*/
public $host;
/**
* POP3 port number.
*
* @var int
*/
public $port;
/**
* POP3 Timeout Value in seconds.
*
* @var int
*/
public $tval;
/**
* POP3 username.
*
* @var string
*/
public $username;
/**
* POP3 password.
*
* @var string
*/
public $password;
/**
* Resource handle for the POP3 connection socket.
*
* @var resource
*/
protected $pop_conn;
/**
* Are we connected?
*
* @var bool
*/
protected $connected = false;
/**
* Error container.
*
* @var array
*/
protected $errors = [];
/**
* Line break constant.
*/
const LE = "\r\n";
/**
* Debug level for no output.
*
* @var int
*/
const DEBUG_OFF = 0;
/**
* Debug level to show server -> client messages
* also shows clients connection errors or errors from server
*
* @var int
*/
const DEBUG_SERVER = 1;
/**
* Debug level to show client -> server and server -> client messages.
*
* @var int
*/
const DEBUG_CLIENT = 2;
/**
* Simple static wrapper for all-in-one POP before SMTP.
*
* @param string $host The hostname to connect to
* @param int|bool $port The port number to connect to
* @param int|bool $timeout The timeout value
* @param string $username
* @param string $password
* @param int $debug_level
*
* @return bool
*/
public static function popBeforeSmtp(
$host,
$port = false,
$timeout = false,
$username = '',
$password = '',
$debug_level = 0
) {
$pop = new self();
return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level);
}
/**
* Authenticate with a POP3 server.
* A connect, login, disconnect sequence
* appropriate for POP-before SMTP authorisation.
*
* @param string $host The hostname to connect to
* @param int|bool $port The port number to connect to
* @param int|bool $timeout The timeout value
* @param string $username
* @param string $password
* @param int $debug_level
*
* @return bool
*/
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
{
$this->host = $host;
//If no port value provided, use default
if (false === $port) {
$this->port = static::DEFAULT_PORT;
} else {
$this->port = (int) $port;
}
//If no timeout value provided, use default
if (false === $timeout) {
$this->tval = static::DEFAULT_TIMEOUT;
} else {
$this->tval = (int) $timeout;
}
$this->do_debug = $debug_level;
$this->username = $username;
$this->password = $password;
//Reset the error log
$this->errors = [];
//Connect
$result = $this->connect($this->host, $this->port, $this->tval);
if ($result) {
$login_result = $this->login($this->username, $this->password);
if ($login_result) {
$this->disconnect();
return true;
}
}
//We need to disconnect regardless of whether the login succeeded
$this->disconnect();
return false;
}
/**
* Connect to a POP3 server.
*
* @param string $host
* @param int|bool $port
* @param int $tval
*
* @return bool
*/
public function connect($host, $port = false, $tval = 30)
{
//Are we already connected?
if ($this->connected) {
return true;
}
//On Windows this will raise a PHP Warning error if the hostname doesn't exist.
//Rather than suppress it with @fsockopen, capture it cleanly instead
set_error_handler(function () {
call_user_func_array([$this, 'catchWarning'], func_get_args());
});
if (false === $port) {
$port = static::DEFAULT_PORT;
}
//Connect to the POP3 server
$errno = 0;
$errstr = '';
$this->pop_conn = fsockopen(
$host, //POP3 Host
$port, //Port #
$errno, //Error Number
$errstr, //Error Message
$tval
); //Timeout (seconds)
//Restore the error handler
restore_error_handler();
//Did we connect?
if (false === $this->pop_conn) {
//It would appear not...
$this->setError(
"Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr"
);
return false;
}
//Increase the stream time-out
stream_set_timeout($this->pop_conn, $tval, 0);
//Get the POP3 server response
$pop3_response = $this->getResponse();
//Check for the +OK
if ($this->checkResponse($pop3_response)) {
//The connection is established and the POP3 server is talking
$this->connected = true;
return true;
}
return false;
}
/**
* Log in to the POP3 server.
* Does not support APOP (RFC 2828, 4949).
*
* @param string $username
* @param string $password
*
* @return bool
*/
public function login($username = '', $password = '')
{
if (!$this->connected) {
$this->setError('Not connected to POP3 server');
return false;
}
if (empty($username)) {
$username = $this->username;
}
if (empty($password)) {
$password = $this->password;
}
//Send the Username
$this->sendString("USER $username" . static::LE);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
//Send the Password
$this->sendString("PASS $password" . static::LE);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
return true;
}
}
return false;
}
/**
* Disconnect from the POP3 server.
*/
public function disconnect()
{
// If could not connect at all, no need to disconnect
if ($this->pop_conn === false) {
return;
}
$this->sendString('QUIT' . static::LE);
// RFC 1939 shows POP3 server sending a +OK response to the QUIT command.
// Try to get it. Ignore any failures here.
try {
$this->getResponse();
} catch (Exception $e) {
//Do nothing
}
//The QUIT command may cause the daemon to exit, which will kill our connection
//So ignore errors here
try {
@fclose($this->pop_conn);
} catch (Exception $e) {
//Do nothing
}
// Clean up attributes.
$this->connected = false;
$this->pop_conn = false;
}
/**
* Get a response from the POP3 server.
*
* @param int $size The maximum number of bytes to retrieve
*
* @return string
*/
protected function getResponse($size = 128)
{
$response = fgets($this->pop_conn, $size);
if ($this->do_debug >= self::DEBUG_SERVER) {
echo 'Server -> Client: ', $response;
}
return $response;
}
/**
* Send raw data to the POP3 server.
*
* @param string $string
*
* @return int
*/
protected function sendString($string)
{
if ($this->pop_conn) {
if ($this->do_debug >= self::DEBUG_CLIENT) { //Show client messages when debug >= 2
echo 'Client -> Server: ', $string;
}
return fwrite($this->pop_conn, $string, strlen($string));
}
return 0;
}
/**
* Checks the POP3 server response.
* Looks for for +OK or -ERR.
*
* @param string $string
*
* @return bool
*/
protected function checkResponse($string)
{
if (strpos($string, '+OK') !== 0) {
$this->setError("Server reported an error: $string");
return false;
}
return true;
}
/**
* Add an error to the internal error store.
* Also display debug output if it's enabled.
*
* @param string $error
*/
protected function setError($error)
{
$this->errors[] = $error;
if ($this->do_debug >= self::DEBUG_SERVER) {
echo '<pre>';
foreach ($this->errors as $e) {
print_r($e);
}
echo '</pre>';
}
}
/**
* Get an array of error messages, if any.
*
* @return array
*/
public function getErrors()
{
return $this->errors;
}
/**
* POP3 connection error handler.
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
*/
protected function catchWarning($errno, $errstr, $errfile, $errline)
{
$this->setError(
'Connecting to the POP3 server raised a PHP warning:' .
"errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline"
);
}
}
"""
"./api/phpmailer/src/SMTP.php" :
"""
<?php
/**
* PHPMailer RFC821 SMTP email transport class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2020 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
/**
* PHPMailer RFC821 SMTP email transport class.
* Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server.
*
* @author Chris Ryan
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
*/
class SMTP
{
/**
* The PHPMailer SMTP version number.
*
* @var string
*/
const VERSION = '6.10.0';
/**
* SMTP line break constant.
*
* @var string
*/
const LE = "\r\n";
/**
* The SMTP port to use if one is not specified.
*
* @var int
*/
const DEFAULT_PORT = 25;
/**
* The SMTPs port to use if one is not specified.
*
* @var int
*/
const DEFAULT_SECURE_PORT = 465;
/**
* The maximum line length allowed by RFC 5321 section 4.5.3.1.6,
* *excluding* a trailing CRLF break.
*
* @see https://www.rfc-editor.org/rfc/rfc5321#section-4.5.3.1.6
*
* @var int
*/
const MAX_LINE_LENGTH = 998;
/**
* The maximum line length allowed for replies in RFC 5321 section 4.5.3.1.5,
* *including* a trailing CRLF line break.
*
* @see https://www.rfc-editor.org/rfc/rfc5321#section-4.5.3.1.5
*
* @var int
*/
const MAX_REPLY_LENGTH = 512;
/**
* Debug level for no output.
*
* @var int
*/
const DEBUG_OFF = 0;
/**
* Debug level to show client -> server messages.
*
* @var int
*/
const DEBUG_CLIENT = 1;
/**
* Debug level to show client -> server and server -> client messages.
*
* @var int
*/
const DEBUG_SERVER = 2;
/**
* Debug level to show connection status, client -> server and server -> client messages.
*
* @var int
*/
const DEBUG_CONNECTION = 3;
/**
* Debug level to show all messages.
*
* @var int
*/
const DEBUG_LOWLEVEL = 4;
/**
* Debug output level.
* Options:
* * self::DEBUG_OFF (`0`) No debug output, default
* * self::DEBUG_CLIENT (`1`) Client commands
* * self::DEBUG_SERVER (`2`) Client commands and server responses
* * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status
* * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages.
*
* @var int
*/
public $do_debug = self::DEBUG_OFF;
/**
* How to handle debug output.
* Options:
* * `echo` Output plain-text as-is, appropriate for CLI
* * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
* * `error_log` Output to error log as configured in php.ini
* Alternatively, you can provide a callable expecting two params: a message string and the debug level:
*
* ```php
* $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
* ```
*
* Alternatively, you can pass in an instance of a PSR-3 compatible logger, though only `debug`
* level output is used:
*
* ```php
* $mail->Debugoutput = new myPsr3Logger;
* ```
*
* @var string|callable|\Psr\Log\LoggerInterface
*/
public $Debugoutput = 'echo';
/**
* Whether to use VERP.
*
* @see https://en.wikipedia.org/wiki/Variable_envelope_return_path
* @see https://www.postfix.org/VERP_README.html Info on VERP
*
* @var bool
*/
public $do_verp = false;
/**
* Whether to use SMTPUTF8.
*
* @see https://www.rfc-editor.org/rfc/rfc6531
*
* @var bool
*/
public $do_smtputf8 = false;
/**
* The timeout value for connection, in seconds.
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2.
* This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure.
*
* @see https://www.rfc-editor.org/rfc/rfc2821#section-4.5.3.2
*
* @var int
*/
public $Timeout = 300;
/**
* How long to wait for commands to complete, in seconds.
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2.
*
* @var int
*/
public $Timelimit = 300;
/**
* Patterns to extract an SMTP transaction id from reply to a DATA command.
* The first capture group in each regex will be used as the ID.
* MS ESMTP returns the message ID, which may not be correct for internal tracking.
*
* @var string[]
*/
protected $smtp_transaction_id_patterns = [
'exim' => '/[\d]{3} OK id=(.*)/',
'sendmail' => '/[\d]{3} 2\.0\.0 (.*) Message/',
'postfix' => '/[\d]{3} 2\.0\.0 Ok: queued as (.*)/',
'Microsoft_ESMTP' => '/[0-9]{3} 2\.[\d]\.0 (.*)@(?:.*) Queued mail for delivery/',
'Amazon_SES' => '/[\d]{3} Ok (.*)/',
'SendGrid' => '/[\d]{3} Ok: queued as (.*)/',
'CampaignMonitor' => '/[\d]{3} 2\.0\.0 OK:([a-zA-Z\d]{48})/',
'Haraka' => '/[\d]{3} Message Queued \((.*)\)/',
'ZoneMTA' => '/[\d]{3} Message queued as (.*)/',
'Mailjet' => '/[\d]{3} OK queued as (.*)/',
];
/**
* Allowed SMTP XCLIENT attributes.
* Must be allowed by the SMTP server. EHLO response is not checked.
*
* @see https://www.postfix.org/XCLIENT_README.html
*
* @var array
*/
public static $xclient_allowed_attributes = [
'NAME', 'ADDR', 'PORT', 'PROTO', 'HELO', 'LOGIN', 'DESTADDR', 'DESTPORT'
];
/**
* The last transaction ID issued in response to a DATA command,
* if one was detected.
*
* @var string|bool|null
*/
protected $last_smtp_transaction_id;
/**
* The socket for the server connection.
*
* @var ?resource
*/
protected $smtp_conn;
/**
* Error information, if any, for the last SMTP command.
*
* @var array
*/
protected $error = [
'error' => '',
'detail' => '',
'smtp_code' => '',
'smtp_code_ex' => '',
];
/**
* The reply the server sent to us for HELO.
* If null, no HELO string has yet been received.
*
* @var string|null
*/
protected $helo_rply;
/**
* The set of SMTP extensions sent in reply to EHLO command.
* Indexes of the array are extension names.
* Value at index 'HELO' or 'EHLO' (according to command that was sent)
* represents the server name. In case of HELO it is the only element of the array.
* Other values can be boolean TRUE or an array containing extension options.
* If null, no HELO/EHLO string has yet been received.
*
* @var array|null
*/
protected $server_caps;
/**
* The most recent reply received from the server.
*
* @var string
*/
protected $last_reply = '';
/**
* Output debugging info via a user-selected method.
*
* @param string $str Debug string to output
* @param int $level The debug level of this message; see DEBUG_* constants
*
* @see SMTP::$Debugoutput
* @see SMTP::$do_debug
*/
protected function edebug($str, $level = 0)
{
if ($level > $this->do_debug) {
return;
}
//Is this a PSR-3 logger?
if ($this->Debugoutput instanceof \Psr\Log\LoggerInterface) {
//Remove trailing line breaks potentially added by calls to SMTP::client_send()
$this->Debugoutput->debug(rtrim($str, "\r\n"));
return;
}
//Avoid clash with built-in function names
if (is_callable($this->Debugoutput) && !in_array($this->Debugoutput, ['error_log', 'html', 'echo'])) {
call_user_func($this->Debugoutput, $str, $level);
return;
}
switch ($this->Debugoutput) {
case 'error_log':
//Don't output, just log
/** @noinspection ForgottenDebugOutputInspection */
error_log($str);
break;
case 'html':
//Cleans up output a bit for a better looking, HTML-safe output
echo gmdate('Y-m-d H:i:s'), ' ', htmlentities(
preg_replace('/[\r\n]+/', '', $str),
ENT_QUOTES,
'UTF-8'
), "<br>\n";
break;
case 'echo':
default:
//Normalize line breaks
$str = preg_replace('/\r\n|\r/m', "\n", $str);
echo gmdate('Y-m-d H:i:s'),
"\t",
//Trim trailing space
trim(
//Indent for readability, except for trailing break
str_replace(
"\n",
"\n \t ",
trim($str)
)
),
"\n";
}
}
/**
* Connect to an SMTP server.
*
* @param string $host SMTP server IP or host name
* @param int $port The port number to connect to
* @param int $timeout How long to wait for the connection to open
* @param array $options An array of options for stream_context_create()
*
* @return bool
*/
public function connect($host, $port = null, $timeout = 30, $options = [])
{
//Clear errors to avoid confusion
$this->setError('');
//Make sure we are __not__ connected
if ($this->connected()) {
//Already connected, generate error
$this->setError('Already connected to a server');
return false;
}
if (empty($port)) {
$port = self::DEFAULT_PORT;
}
//Connect to the SMTP server
$this->edebug(
"Connection: opening to $host:$port, timeout=$timeout, options=" .
(count($options) > 0 ? var_export($options, true) : 'array()'),
self::DEBUG_CONNECTION
);
$this->smtp_conn = $this->getSMTPConnection($host, $port, $timeout, $options);
if ($this->smtp_conn === false) {
//Error info already set inside `getSMTPConnection()`
return false;
}
$this->edebug('Connection: opened', self::DEBUG_CONNECTION);
//Get any announcement
$this->last_reply = $this->get_lines();
$this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
$responseCode = (int)substr($this->last_reply, 0, 3);
if ($responseCode === 220) {
return true;
}
//Anything other than a 220 response means something went wrong
//RFC 5321 says the server will wait for us to send a QUIT in response to a 554 error
//https://www.rfc-editor.org/rfc/rfc5321#section-3.1
if ($responseCode === 554) {
$this->quit();
}
//This will handle 421 responses which may not wait for a QUIT (e.g. if the server is being shut down)
$this->edebug('Connection: closing due to error', self::DEBUG_CONNECTION);
$this->close();
return false;
}
/**
* Create connection to the SMTP server.
*
* @param string $host SMTP server IP or host name
* @param int $port The port number to connect to
* @param int $timeout How long to wait for the connection to open
* @param array $options An array of options for stream_context_create()
*
* @return false|resource
*/
protected function getSMTPConnection($host, $port = null, $timeout = 30, $options = [])
{
static $streamok;
//This is enabled by default since 5.0.0 but some providers disable it
//Check this once and cache the result
if (null === $streamok) {
$streamok = function_exists('stream_socket_client');
}
$errno = 0;
$errstr = '';
if ($streamok) {
$socket_context = stream_context_create($options);
set_error_handler(function () {
call_user_func_array([$this, 'errorHandler'], func_get_args());
});
$connection = stream_socket_client(
$host . ':' . $port,
$errno,
$errstr,
$timeout,
STREAM_CLIENT_CONNECT,
$socket_context
);
} else {
//Fall back to fsockopen which should work in more places, but is missing some features
$this->edebug(
'Connection: stream_socket_client not available, falling back to fsockopen',
self::DEBUG_CONNECTION
);
set_error_handler(function () {
call_user_func_array([$this, 'errorHandler'], func_get_args());
});
$connection = fsockopen(
$host,
$port,
$errno,
$errstr,
$timeout
);
}
restore_error_handler();
//Verify we connected properly
if (!is_resource($connection)) {
$this->setError(
'Failed to connect to server',
'',
(string) $errno,
$errstr
);
$this->edebug(
'SMTP ERROR: ' . $this->error['error']
. ": $errstr ($errno)",
self::DEBUG_CLIENT
);
return false;
}
//SMTP server can take longer to respond, give longer timeout for first read
//Windows does not have support for this timeout function
if (strpos(PHP_OS, 'WIN') !== 0) {
$max = (int)ini_get('max_execution_time');
//Don't bother if unlimited, or if set_time_limit is disabled
if (0 !== $max && $timeout > $max && strpos(ini_get('disable_functions'), 'set_time_limit') === false) {
@set_time_limit($timeout);
}
stream_set_timeout($connection, $timeout, 0);
}
return $connection;
}
/**
* Initiate a TLS (encrypted) session.
*
* @return bool
*/
public function startTLS()
{
if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) {
return false;
}
//Allow the best TLS version(s) we can
$crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
//PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
//so add them back in manually if we can
if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
}
//Begin encrypted connection
set_error_handler(function () {
call_user_func_array([$this, 'errorHandler'], func_get_args());
});
$crypto_ok = stream_socket_enable_crypto(
$this->smtp_conn,
true,
$crypto_method
);
restore_error_handler();
return (bool) $crypto_ok;
}
/**
* Perform SMTP authentication.
* Must be run after hello().
*
* @see hello()
*
* @param string $username The user name
* @param string $password The password
* @param string $authtype The auth type (CRAM-MD5, PLAIN, LOGIN, XOAUTH2)
* @param OAuthTokenProvider $OAuth An optional OAuthTokenProvider instance for XOAUTH2 authentication
*
* @return bool True if successfully authenticated
*/
public function authenticate(
$username,
$password,
$authtype = null,
$OAuth = null
) {
if (!$this->server_caps) {
$this->setError('Authentication is not allowed before HELO/EHLO');
return false;
}
if (array_key_exists('EHLO', $this->server_caps)) {
//SMTP extensions are available; try to find a proper authentication method
if (!array_key_exists('AUTH', $this->server_caps)) {
$this->setError('Authentication is not allowed at this stage');
//'at this stage' means that auth may be allowed after the stage changes
//e.g. after STARTTLS
return false;
}
$this->edebug('Auth method requested: ' . ($authtype ?: 'UNSPECIFIED'), self::DEBUG_LOWLEVEL);
$this->edebug(
'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']),
self::DEBUG_LOWLEVEL
);
//If we have requested a specific auth type, check the server supports it before trying others
if (null !== $authtype && !in_array($authtype, $this->server_caps['AUTH'], true)) {
$this->edebug('Requested auth method not available: ' . $authtype, self::DEBUG_LOWLEVEL);
$authtype = null;
}
if (empty($authtype)) {
//If no auth mechanism is specified, attempt to use these, in this order
//Try CRAM-MD5 first as it's more secure than the others
foreach (['CRAM-MD5', 'LOGIN', 'PLAIN', 'XOAUTH2'] as $method) {
if (in_array($method, $this->server_caps['AUTH'], true)) {
$authtype = $method;
break;
}
}
if (empty($authtype)) {
$this->setError('No supported authentication methods found');
return false;
}
$this->edebug('Auth method selected: ' . $authtype, self::DEBUG_LOWLEVEL);
}
if (!in_array($authtype, $this->server_caps['AUTH'], true)) {
$this->setError("The requested authentication method \"$authtype\" is not supported by the server");
return false;
}
} elseif (empty($authtype)) {
$authtype = 'LOGIN';
}
switch ($authtype) {
case 'PLAIN':
//Start authentication
if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
return false;
}
//Send encoded username and password
if (
//Format from https://www.rfc-editor.org/rfc/rfc4616#section-2
//We skip the first field (it's forgery), so the string starts with a null byte
!$this->sendCommand(
'User & Password',
base64_encode("\0" . $username . "\0" . $password),
235
)
) {
return false;
}
break;
case 'LOGIN':
//Start authentication
if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
return false;
}
if (!$this->sendCommand('Username', base64_encode($username), 334)) {
return false;
}
if (!$this->sendCommand('Password', base64_encode($password), 235)) {
return false;
}
break;
case 'CRAM-MD5':
//Start authentication
if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
return false;
}
//Get the challenge
$challenge = base64_decode(substr($this->last_reply, 4));
//Build the response
$response = $username . ' ' . $this->hmac($challenge, $password);
//send encoded credentials
return $this->sendCommand('Username', base64_encode($response), 235);
case 'XOAUTH2':
//The OAuth instance must be set up prior to requesting auth.
if (null === $OAuth) {
return false;
}
$oauth = $OAuth->getOauth64();
//Start authentication
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
return false;
}
break;
default:
$this->setError("Authentication method \"$authtype\" is not supported");
return false;
}
return true;
}
/**
* Calculate an MD5 HMAC hash.
* Works like hash_hmac('md5', $data, $key)
* in case that function is not available.
*
* @param string $data The data to hash
* @param string $key The key to hash with
*
* @return string
*/
protected function hmac($data, $key)
{
if (function_exists('hash_hmac')) {
return hash_hmac('md5', $data, $key);
}
//The following borrowed from
//https://www.php.net/manual/en/function.mhash.php#27225
//RFC 2104 HMAC implementation for php.
//Creates an md5 HMAC.
//Eliminates the need to install mhash to compute a HMAC
//by Lance Rushing
$bytelen = 64; //byte length for md5
if (strlen($key) > $bytelen) {
$key = pack('H*', md5($key));
}
$key = str_pad($key, $bytelen, chr(0x00));
$ipad = str_pad('', $bytelen, chr(0x36));
$opad = str_pad('', $bytelen, chr(0x5c));
$k_ipad = $key ^ $ipad;
$k_opad = $key ^ $opad;
return md5($k_opad . pack('H*', md5($k_ipad . $data)));
}
/**
* Check connection state.
*
* @return bool True if connected
*/
public function connected()
{
if (is_resource($this->smtp_conn)) {
$sock_status = stream_get_meta_data($this->smtp_conn);
if ($sock_status['eof']) {
//The socket is valid but we are not connected
$this->edebug(
'SMTP NOTICE: EOF caught while checking if connected',
self::DEBUG_CLIENT
);
$this->close();
return false;
}
return true; //everything looks good
}
return false;
}
/**
* Close the socket and clean up the state of the class.
* Don't use this function without first trying to use QUIT.
*
* @see quit()
*/
public function close()
{
$this->server_caps = null;
$this->helo_rply = null;
if (is_resource($this->smtp_conn)) {
//Close the connection and cleanup
fclose($this->smtp_conn);
$this->smtp_conn = null; //Makes for cleaner serialization
$this->edebug('Connection: closed', self::DEBUG_CONNECTION);
}
}
/**
* Send an SMTP DATA command.
* Issues a data command and sends the msg_data to the server,
* finalizing the mail transaction. $msg_data is the message
* that is to be sent with the headers. Each header needs to be
* on a single line followed by a <CRLF> with the message headers
* and the message body being separated by an additional <CRLF>.
* Implements RFC 821: DATA <CRLF>.
*
* @param string $msg_data Message data to send
*
* @return bool
*/
public function data($msg_data)
{
//This will use the standard timelimit
if (!$this->sendCommand('DATA', 'DATA', 354)) {
return false;
}
/* The server is ready to accept data!
* According to rfc821 we should not send more than 1000 characters on a single line (including the LE)
* so we will break the data up into lines by \r and/or \n then if needed we will break each of those into
* smaller lines to fit within the limit.
* We will also look for lines that start with a '.' and prepend an additional '.'.
* NOTE: this does not count towards line-length limit.
*/
//Normalize line breaks before exploding
$lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data));
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
* of the first line (':' separated) does not contain a space then it _should_ be a header, and we will
* process all lines before a blank line as headers.
*/
$field = substr($lines[0], 0, strpos($lines[0], ':'));
$in_headers = false;
if (!empty($field) && strpos($field, ' ') === false) {
$in_headers = true;
}
foreach ($lines as $line) {
$lines_out = [];
if ($in_headers && $line === '') {
$in_headers = false;
}
//Break this line up into several smaller lines if it's too long
//Micro-optimisation: isset($str[$len]) is faster than (strlen($str) > $len),
while (isset($line[self::MAX_LINE_LENGTH])) {
//Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on
//so as to avoid breaking in the middle of a word
$pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' ');
//Deliberately matches both false and 0
if (!$pos) {
//No nice break found, add a hard break
$pos = self::MAX_LINE_LENGTH - 1;
$lines_out[] = substr($line, 0, $pos);
$line = substr($line, $pos);
} else {
//Break at the found point
$lines_out[] = substr($line, 0, $pos);
//Move along by the amount we dealt with
$line = substr($line, $pos + 1);
}
//If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1
if ($in_headers) {
$line = "\t" . $line;
}
}
$lines_out[] = $line;
//Send the lines to the server
foreach ($lines_out as $line_out) {
//Dot-stuffing as per RFC5321 section 4.5.2
//https://www.rfc-editor.org/rfc/rfc5321#section-4.5.2
if (!empty($line_out) && $line_out[0] === '.') {
$line_out = '.' . $line_out;
}
$this->client_send($line_out . static::LE, 'DATA');
}
}
//Message data has been sent, complete the command
//Increase timelimit for end of DATA command
$savetimelimit = $this->Timelimit;
$this->Timelimit *= 2;
$result = $this->sendCommand('DATA END', '.', 250);
$this->recordLastTransactionID();
//Restore timelimit
$this->Timelimit = $savetimelimit;
return $result;
}
/**
* Send an SMTP HELO or EHLO command.
* Used to identify the sending server to the receiving server.
* This makes sure that client and server are in a known state.
* Implements RFC 821: HELO <SP> <domain> <CRLF>
* and RFC 2821 EHLO.
*
* @param string $host The host name or IP to connect to
*
* @return bool
*/
public function hello($host = '')
{
//Try extended hello first (RFC 2821)
if ($this->sendHello('EHLO', $host)) {
return true;
}
//Some servers shut down the SMTP service here (RFC 5321)
if (substr($this->helo_rply, 0, 3) == '421') {
return false;
}
return $this->sendHello('HELO', $host);
}
/**
* Send an SMTP HELO or EHLO command.
* Low-level implementation used by hello().
*
* @param string $hello The HELO string
* @param string $host The hostname to say we are
*
* @return bool
*
* @see hello()
*/
protected function sendHello($hello, $host)
{
$noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250);
$this->helo_rply = $this->last_reply;
if ($noerror) {
$this->parseHelloFields($hello);
} else {
$this->server_caps = null;
}
return $noerror;
}
/**
* Parse a reply to HELO/EHLO command to discover server extensions.
* In case of HELO, the only parameter that can be discovered is a server name.
*
* @param string $type `HELO` or `EHLO`
*/
protected function parseHelloFields($type)
{
$this->server_caps = [];
$lines = explode("\n", $this->helo_rply);
foreach ($lines as $n => $s) {
//First 4 chars contain response code followed by - or space
$s = trim(substr($s, 4));
if (empty($s)) {
continue;
}
$fields = explode(' ', $s);
if (!empty($fields)) {
if (!$n) {
$name = $type;
$fields = $fields[0];
} else {
$name = array_shift($fields);
switch ($name) {
case 'SIZE':
$fields = ($fields ? $fields[0] : 0);
break;
case 'AUTH':
if (!is_array($fields)) {
$fields = [];
}
break;
default:
$fields = true;
}
}
$this->server_caps[$name] = $fields;
}
}
}
/**
* Send an SMTP MAIL command.
* Starts a mail transaction from the email address specified in
* $from. Returns true if successful or false otherwise. If True
* the mail transaction is started and then one or more recipient
* commands may be called followed by a data command.
* Implements RFC 821: MAIL <SP> FROM:<reverse-path> <CRLF> and
* two extensions, namely XVERP and SMTPUTF8.
*
* The server's EHLO response is not checked. If use of either
* extensions is enabled even though the server does not support
* that, mail submission will fail.
*
* XVERP is documented at https://www.postfix.org/VERP_README.html
* and SMTPUTF8 is specified in RFC 6531.
*
* @param string $from Source address of this message
*
* @return bool
*/
public function mail($from)
{
$useVerp = ($this->do_verp ? ' XVERP' : '');
$useSmtputf8 = ($this->do_smtputf8 ? ' SMTPUTF8' : '');
return $this->sendCommand(
'MAIL FROM',
'MAIL FROM:<' . $from . '>' . $useSmtputf8 . $useVerp,
250
);
}
/**
* Send an SMTP QUIT command.
* Closes the socket if there is no error or the $close_on_error argument is true.
* Implements from RFC 821: QUIT <CRLF>.
*
* @param bool $close_on_error Should the connection close if an error occurs?
*
* @return bool
*/
public function quit($close_on_error = true)
{
$noerror = $this->sendCommand('QUIT', 'QUIT', 221);
$err = $this->error; //Save any error
if ($noerror || $close_on_error) {
$this->close();
$this->error = $err; //Restore any error from the quit command
}
return $noerror;
}
/**
* Send an SMTP RCPT command.
* Sets the TO argument to $toaddr.
* Returns true if the recipient was accepted false if it was rejected.
* Implements from RFC 821: RCPT <SP> TO:<forward-path> <CRLF>.
*
* @param string $address The address the message is being sent to
* @param string $dsn Comma separated list of DSN notifications. NEVER, SUCCESS, FAILURE
* or DELAY. If you specify NEVER all other notifications are ignored.
*
* @return bool
*/
public function recipient($address, $dsn = '')
{
if (empty($dsn)) {
$rcpt = 'RCPT TO:<' . $address . '>';
} else {
$dsn = strtoupper($dsn);
$notify = [];
if (strpos($dsn, 'NEVER') !== false) {
$notify[] = 'NEVER';
} else {
foreach (['SUCCESS', 'FAILURE', 'DELAY'] as $value) {
if (strpos($dsn, $value) !== false) {
$notify[] = $value;
}
}
}
$rcpt = 'RCPT TO:<' . $address . '> NOTIFY=' . implode(',', $notify);
}
return $this->sendCommand(
'RCPT TO',
$rcpt,
[250, 251]
);
}
/**
* Send SMTP XCLIENT command to server and check its return code.
*
* @return bool True on success
*/
public function xclient(array $vars)
{
$xclient_options = "";
foreach ($vars as $key => $value) {
if (in_array($key, SMTP::$xclient_allowed_attributes)) {
$xclient_options .= " {$key}={$value}";
}
}
if (!$xclient_options) {
return true;
}
return $this->sendCommand('XCLIENT', 'XCLIENT' . $xclient_options, 250);
}
/**
* Send an SMTP RSET command.
* Abort any transaction that is currently in progress.
* Implements RFC 821: RSET <CRLF>.
*
* @return bool True on success
*/
public function reset()
{
return $this->sendCommand('RSET', 'RSET', 250);
}
/**
* Send a command to an SMTP server and check its return code.
*
* @param string $command The command name - not sent to the server
* @param string $commandstring The actual command to send
* @param int|array $expect One or more expected integer success codes
*
* @return bool True on success
*/
protected function sendCommand($command, $commandstring, $expect)
{
if (!$this->connected()) {
$this->setError("Called $command without being connected");
return false;
}
//Reject line breaks in all commands
if ((strpos($commandstring, "\n") !== false) || (strpos($commandstring, "\r") !== false)) {
$this->setError("Command '$command' contained line breaks");
return false;
}
$this->client_send($commandstring . static::LE, $command);
$this->last_reply = $this->get_lines();
//Fetch SMTP code and possible error code explanation
$matches = [];
if (preg_match('/^([\d]{3})[ -](?:([\d]\\.[\d]\\.[\d]{1,2}) )?/', $this->last_reply, $matches)) {
$code = (int) $matches[1];
$code_ex = (count($matches) > 2 ? $matches[2] : null);
//Cut off error code from each response line
$detail = preg_replace(
"/{$code}[ -]" .
($code_ex ? str_replace('.', '\\.', $code_ex) . ' ' : '') . '/m',
'',
$this->last_reply
);
} else {
//Fall back to simple parsing if regex fails
$code = (int) substr($this->last_reply, 0, 3);
$code_ex = null;
$detail = substr($this->last_reply, 4);
}
$this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
if (!in_array($code, (array) $expect, true)) {
$this->setError(
"$command command failed",
$detail,
$code,
$code_ex
);
$this->edebug(
'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply,
self::DEBUG_CLIENT
);
return false;
}
//Don't clear the error store when using keepalive
if ($command !== 'RSET') {
$this->setError('');
}
return true;
}
/**
* Send an SMTP SAML command.
* Starts a mail transaction from the email address specified in $from.
* Returns true if successful or false otherwise. If True
* the mail transaction is started and then one or more recipient
* commands may be called followed by a data command. This command
* will send the message to the users terminal if they are logged
* in and send them an email.
* Implements RFC 821: SAML <SP> FROM:<reverse-path> <CRLF>.
*
* @param string $from The address the message is from
*
* @return bool
*/
public function sendAndMail($from)
{
return $this->sendCommand('SAML', "SAML FROM:$from", 250);
}
/**
* Send an SMTP VRFY command.
*
* @param string $name The name to verify
*
* @return bool
*/
public function verify($name)
{
return $this->sendCommand('VRFY', "VRFY $name", [250, 251]);
}
/**
* Send an SMTP NOOP command.
* Used to keep keep-alives alive, doesn't actually do anything.
*
* @return bool
*/
public function noop()
{
return $this->sendCommand('NOOP', 'NOOP', 250);
}
/**
* Send an SMTP TURN command.
* This is an optional command for SMTP that this class does not support.
* This method is here to make the RFC821 Definition complete for this class
* and _may_ be implemented in future.
* Implements from RFC 821: TURN <CRLF>.
*
* @return bool
*/
public function turn()
{
$this->setError('The SMTP TURN command is not implemented');
$this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT);
return false;
}
/**
* Send raw data to the server.
*
* @param string $data The data to send
* @param string $command Optionally, the command this is part of, used only for controlling debug output
*
* @return int|bool The number of bytes sent to the server or false on error
*/
public function client_send($data, $command = '')
{
//If SMTP transcripts are left enabled, or debug output is posted online
//it can leak credentials, so hide credentials in all but lowest level
if (
self::DEBUG_LOWLEVEL > $this->do_debug &&
in_array($command, ['User & Password', 'Username', 'Password'], true)
) {
$this->edebug('CLIENT -> SERVER: [credentials hidden]', self::DEBUG_CLIENT);
} else {
$this->edebug('CLIENT -> SERVER: ' . $data, self::DEBUG_CLIENT);
}
set_error_handler(function () {
call_user_func_array([$this, 'errorHandler'], func_get_args());
});
$result = fwrite($this->smtp_conn, $data);
restore_error_handler();
return $result;
}
/**
* Get the latest error.
*
* @return array
*/
public function getError()
{
return $this->error;
}
/**
* Get SMTP extensions available on the server.
*
* @return array|null
*/
public function getServerExtList()
{
return $this->server_caps;
}
/**
* Get metadata about the SMTP server from its HELO/EHLO response.
* The method works in three ways, dependent on argument value and current state:
* 1. HELO/EHLO has not been sent - returns null and populates $this->error.
* 2. HELO has been sent -
* $name == 'HELO': returns server name
* $name == 'EHLO': returns boolean false
* $name == any other string: returns null and populates $this->error
* 3. EHLO has been sent -
* $name == 'HELO'|'EHLO': returns the server name
* $name == any other string: if extension $name exists, returns True
* or its options (e.g. AUTH mechanisms supported). Otherwise returns False.
*
* @param string $name Name of SMTP extension or 'HELO'|'EHLO'
*
* @return string|bool|null
*/
public function getServerExt($name)
{
if (!$this->server_caps) {
$this->setError('No HELO/EHLO was sent');
return null;
}
if (!array_key_exists($name, $this->server_caps)) {
if ('HELO' === $name) {
return $this->server_caps['EHLO'];
}
if ('EHLO' === $name || array_key_exists('EHLO', $this->server_caps)) {
return false;
}
$this->setError('HELO handshake was used; No information about server extensions available');
return null;
}
return $this->server_caps[$name];
}
/**
* Get the last reply from the server.
*
* @return string
*/
public function getLastReply()
{
return $this->last_reply;
}
/**
* Read the SMTP server's response.
* Either before eof or socket timeout occurs on the operation.
* With SMTP we can tell if we have more lines to read if the
* 4th character is '-' symbol. If it is a space then we don't
* need to read anything else.
*
* @return string
*/
protected function get_lines()
{
//If the connection is bad, give up straight away
if (!is_resource($this->smtp_conn)) {
return '';
}
$data = '';
$endtime = 0;
stream_set_timeout($this->smtp_conn, $this->Timeout);
if ($this->Timelimit > 0) {
$endtime = time() + $this->Timelimit;
}
$selR = [$this->smtp_conn];
$selW = null;
while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
//Must pass vars in here as params are by reference
//solution for signals inspired by https://github.com/symfony/symfony/pull/6540
set_error_handler(function () {
call_user_func_array([$this, 'errorHandler'], func_get_args());
});
$n = stream_select($selR, $selW, $selW, $this->Timelimit);
restore_error_handler();
if ($n === false) {
$message = $this->getError()['detail'];
$this->edebug(
'SMTP -> get_lines(): select failed (' . $message . ')',
self::DEBUG_LOWLEVEL
);
//stream_select returns false when the `select` system call is interrupted
//by an incoming signal, try the select again
if (stripos($message, 'interrupted system call') !== false) {
$this->edebug(
'SMTP -> get_lines(): retrying stream_select',
self::DEBUG_LOWLEVEL
);
$this->setError('');
continue;
}
break;
}
if (!$n) {
$this->edebug(
'SMTP -> get_lines(): select timed-out in (' . $this->Timelimit . ' sec)',
self::DEBUG_LOWLEVEL
);
break;
}
//Deliberate noise suppression - errors are handled afterwards
$str = @fgets($this->smtp_conn, self::MAX_REPLY_LENGTH);
$this->edebug('SMTP INBOUND: "' . trim($str) . '"', self::DEBUG_LOWLEVEL);
$data .= $str;
//If response is only 3 chars (not valid, but RFC5321 S4.2 says it must be handled),
//or 4th character is a space or a line break char, we are done reading, break the loop.
//String array access is a significant micro-optimisation over strlen
if (!isset($str[3]) || $str[3] === ' ' || $str[3] === "\r" || $str[3] === "\n") {
break;
}
//Timed-out? Log and break
$info = stream_get_meta_data($this->smtp_conn);
if ($info['timed_out']) {
$this->edebug(
'SMTP -> get_lines(): stream timed-out (' . $this->Timeout . ' sec)',
self::DEBUG_LOWLEVEL
);
break;
}
//Now check if reads took too long
if ($endtime && time() > $endtime) {
$this->edebug(
'SMTP -> get_lines(): timelimit reached (' .
$this->Timelimit . ' sec)',
self::DEBUG_LOWLEVEL
);
break;
}
}
return $data;
}
/**
* Enable or disable VERP address generation.
*
* @param bool $enabled
*/
public function setVerp($enabled = false)
{
$this->do_verp = $enabled;
}
/**
* Get VERP address generation mode.
*
* @return bool
*/
public function getVerp()
{
return $this->do_verp;
}
/**
* Enable or disable use of SMTPUTF8.
*
* @param bool $enabled
*/
public function setSMTPUTF8($enabled = false)
{
$this->do_smtputf8 = $enabled;
}
/**
* Get SMTPUTF8 use.
*
* @return bool
*/
public function getSMTPUTF8()
{
return $this->do_smtputf8;
}
/**
* Set error messages and codes.
*
* @param string $message The error message
* @param string $detail Further detail on the error
* @param string $smtp_code An associated SMTP error code
* @param string $smtp_code_ex Extended SMTP code
*/
protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ex = '')
{
$this->error = [
'error' => $message,
'detail' => $detail,
'smtp_code' => $smtp_code,
'smtp_code_ex' => $smtp_code_ex,
];
}
/**
* Set debug output method.
*
* @param string|callable $method The name of the mechanism to use for debugging output, or a callable to handle it
*/
public function setDebugOutput($method = 'echo')
{
$this->Debugoutput = $method;
}
/**
* Get debug output method.
*
* @return string
*/
public function getDebugOutput()
{
return $this->Debugoutput;
}
/**
* Set debug output level.
*
* @param int $level
*/
public function setDebugLevel($level = 0)
{
$this->do_debug = $level;
}
/**
* Get debug output level.
*
* @return int
*/
public function getDebugLevel()
{
return $this->do_debug;
}
/**
* Set SMTP timeout.
*
* @param int $timeout The timeout duration in seconds
*/
public function setTimeout($timeout = 0)
{
$this->Timeout = $timeout;
}
/**
* Get SMTP timeout.
*
* @return int
*/
public function getTimeout()
{
return $this->Timeout;
}
/**
* Reports an error number and string.
*
* @param int $errno The error number returned by PHP
* @param string $errmsg The error message returned by PHP
* @param string $errfile The file the error occurred in
* @param int $errline The line number the error occurred on
*/
protected function errorHandler($errno, $errmsg, $errfile = '', $errline = 0)
{
$notice = 'Connection failed.';
$this->setError(
$notice,
$errmsg,
(string) $errno
);
$this->edebug(
"$notice Error #$errno: $errmsg [$errfile line $errline]",
self::DEBUG_CONNECTION
);
}
/**
* Extract and return the ID of the last SMTP transaction based on
* a list of patterns provided in SMTP::$smtp_transaction_id_patterns.
* Relies on the host providing the ID in response to a DATA command.
* If no reply has been received yet, it will return null.
* If no pattern was matched, it will return false.
*
* @return bool|string|null
*/
protected function recordLastTransactionID()
{
$reply = $this->getLastReply();
if (empty($reply)) {
$this->last_smtp_transaction_id = null;
} else {
$this->last_smtp_transaction_id = false;
foreach ($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) {
$matches = [];
if (preg_match($smtp_transaction_id_pattern, $reply, $matches)) {
$this->last_smtp_transaction_id = trim($matches[1]);
break;
}
}
}
return $this->last_smtp_transaction_id;
}
/**
* Get the queue/transaction ID of the last SMTP transaction
* If no reply has been received yet, it will return null.
* If no pattern was matched, it will return false.
*
* @return bool|string|null
*
* @see recordLastTransactionID()
*/
public function getLastTransactionID()
{
return $this->last_smtp_transaction_id;
}
}
"""
"./api/send_mail.php" :
"""
<?php
// Omogočimo prikazovanje napak za lažje razhroščevanje med razvojem.
// V produkciji to zakomentirajte ali nastavite na 0.
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Uvozimo potrebne PHPMailer razrede v globalni imenski prostor.
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
// Vključimo datoteke knjižnice PHPMailer.
// Pot je relativna na lokacijo te skripte (api/send_mail.php).
require 'phpmailer/Exception.php';
require 'phpmailer/PHPMailer.php';
require 'phpmailer/SMTP.php';
// Vključimo našo varno konfiguracijsko datoteko z gesli.
require 'config.php';
// Nastavimo glavo (header) odgovora, da bo brskalnik vedel, da pričakuje JSON.
header('Content-Type: application/json');
// Pripravimo privzet odgovor. Če pride do napake pred pošiljanjem, bo to poslano nazaj.
$response = ['success' => false, 'message' => 'Neznana napaka. Prosimo, kontaktirajte administratorja.'];
// 1. KORAK: Preverimo, ali je bila zahteva poslana z metodo POST.
// S tem preprečimo, da bi kdo do skripte dostopal neposredno preko URL-ja.
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
$response['message'] = 'Nedovoljen dostop.';
echo json_encode($response);
exit;
}
// 2. KORAK: Preberemo JSON podatke, ki jih je poslal JavaScript (fetch).
// Standardna PHP spremenljivka $_POST ne deluje za JSON vsebino.
$json_data = file_get_contents('php://input');
$data = json_decode($json_data, true);
// Preverimo, če so podatki pravilno dekodirani in če vsebujejo vse potrebne ključe.
if (!$data || !isset($data['name']) || !isset($data['email']) || !isset($data['message'])) {
$response['message'] = 'Manjkajoči podatki. Prosimo, izpolnite vsa polja.';
echo json_encode($response);
exit;
}
// 3. KORAK: Očistimo in validiramo prejete podatke.
$name = trim($data['name']);
$email = trim($data['email']);
$message = trim($data['message']);
if (empty($name)) {
$response['message'] = 'Prosimo, vnesite vaše ime in priimek.';
echo json_encode($response);
exit;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$response['message'] = 'Prosimo, vnesite veljaven e-poštni naslov.';
echo json_encode($response);
exit;
}
if (empty($message)) {
$response['message'] = 'Prosimo, vnesite vaše sporočilo.';
echo json_encode($response);
exit;
}
// 4. KORAK: Ustvarimo novo instanco PHPMailer.
// `true` v konstruktorju omogoči izjeme (exceptions), kar je boljši način za obravnavo napak.
$mail = new PHPMailer(true);
try {
// === Nastavitve strežnika (uporabimo konstante iz config.php) ===
// Za razhroščevanje - prikaže podroben izpis dogajanja. V produkciji nastavite na SMTP::DEBUG_OFF.
// $mail->SMTPDebug = SMTP::DEBUG_SERVER;
$mail->isSMTP();
$mail->Host = SMTP_HOST;
$mail->SMTPAuth = true;
$mail->Username = SMTP_USERNAME;
$mail->Password = SMTP_PASSWORD;
$mail->SMTPSecure = SMTP_SECURE;
$mail->Port = SMTP_PORT;
// Nastavimo kodiranje znakov na UTF-8 za pravilno podporo šumnikom.
$mail->CharSet = 'UTF-8';
// === Prejemniki ===
// Pošiljatelj - to mora biti naslov, s katerim se prijavljate (info@herminamerc.si).
// Ime pošiljatelja pa je ime, ki ga je vpisala oseba v obrazec.
$mail->setFrom(SMTP_USERNAME, $name);
// Prejemnik - to ste vi (lastnik spletne strani).
$mail->addAddress(SMTP_USERNAME, 'Hermina Merc - Spletna Stran');
// Naslov za odgovor (Reply-To) - KLJUČEN DEL!
// To nastavimo na e-mail osebe, ki je izpolnila obrazec.
// Ko boste v vašem e-mail klientu kliknili "Odgovori", boste odgovorili neposredno tej osebi.
$mail->addReplyTo($email, $name);
// === Vsebina e-sporočila ===
$mail->isHTML(false); // Pošljemo kot navadno besedilo, ne HTML.
$mail->Subject = 'Novo sporočilo s spletne strani herminamerc.si';
// Sestavimo telo sporočila.
$mail->Body = "Prejeli ste novo sporočilo preko kontaktnega obrazca.\n\n" .
"==================================================\n" .
"Ime in priimek: " . $name . "\n" .
"E-mail naslov: " . $email . "\n" .
"==================================================\n\n" .
"Sporočilo:\n" .
"--------------------------------------------------\n" .
$message . "\n" .
"--------------------------------------------------\n";
// 5. KORAK: Pošljemo e-sporočilo.
$mail->send();
// Če je pošiljanje uspelo, pripravimo uspešen odgovor.
$response['success'] = true;
$response['message'] = 'Hvala za vaše sporočilo! Odgovorili vam bomo v najkrajšem možnem času.';
} catch (Exception $e) {
// Če je prišlo do napake med pošiljanjem, jo ujamemo.
$response['success'] = false;
$response['message'] = 'Sporočila ni bilo mogoče poslati. Prosimo, poskusite znova kasneje.';
// Za razhroščevanje: zabeležimo dejansko napako v strežniški log (ne prikažemo je uporabniku).
// Na strežniku omogočite pisanje v error log.
error_log("PHPMailer napaka: " . $mail->ErrorInfo);
}
// 6. KORAK: Pošljemo JSON odgovor nazaj JavaScriptu.
echo json_encode($response);
?>"""
"./assets/css/base/_reset.css" :
"""
/* /assets/css/base/_reset.css */
/* --- OSNOVNI STILI IN RESET --- */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
font-size: 16px;
}
body {
font-family: var(--font-body);
color: var(--color-text);
background-color: var(--color-background);
line-height: 1.7;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Ta blok je bil odstranjen, ker je preprečeval drsenje.
Nova, boljša logika je v datoteki pages/_homepage.css */"""
"./assets/css/base/_typography.css" :
"""
/* /assets/css/base/_typography.css */
h1, h2, h3 {
font-family: var(--font-heading);
font-weight: 700;
line-height: 1.2;
margin-bottom: var(--spacing-m);
color: var(--color-primary-accent); /* SPREMEMBA: Vsi naslovi so sedaj v primarni barvi */
}
p {
margin-bottom: var(--spacing-m);
}
a {
color: var(--color-primary-accent);
text-decoration: none;
transition: color var(--transition-fast);
}
a:hover {
color: var(--color-primary-accent-dark);
}
/* === DODAN POMOŽNI RAZRED ZA STILIRANJE BESEDILA === */
.text-accent-uppercase {
color: var(--color-primary-accent);
text-transform: uppercase;
}"""
"./assets/css/base/_variables.css" :
"""
/* /assets/css/base/_variables.css */
/* --- :ROOT - CSS SPREMENLJIVKE --- */
:root {
--font-heading: 'Playfair Display', serif;
--font-body: 'Montserrat', sans-serif;
--color-text: #2c3e50; /* Temna, skoraj črna-modra */
--color-background: #fdfdfd;
--color-primary-accent: #0804fc; /* NOVA GLAVNA BARVA */
--color-primary-accent-dark: #0603c9; /* Temnejši odtenek nove barve */
--color-white: #ffffff;
--color-border: #e0e0e0;
--spacing-xs: 0.25rem;
--spacing-s: 0.5rem;
--spacing-m: 1rem;
--spacing-l: 2rem;
--spacing-xl: 4rem;
--shadow-light: 0 4px 6px rgba(0, 0, 0, 0.05);
--shadow-medium: 0 8px 24px rgba(0, 0, 0, 0.1);
--transition-fast: 0.2s ease-in-out;
--transition-medium: 0.5s ease-in-out;
}"""
"./assets/css/code_export.txt" :
"""
"./base/_reset.css" :
"""
/* /assets/css/base/_reset.css */
/* --- OSNOVNI STILI IN RESET --- */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
font-size: 16px;
overflow-x: hidden;
}
body {
font-family: var(--font-body);
color: var(--color-text);
background-color: var(--color-background);
line-height: 1.7;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-x: hidden;
}
/* POSEBEN STIL ZA DOMAČO STRAN, DA PREPREČI DRSENJE STRANI */
body.homepage {
overflow: hidden;
}"""
"./base/_typography.css" :
"""
/* /assets/css/base/_typography.css */
h1, h2, h3 {
font-family: var(--font-heading);
font-weight: 700;
line-height: 1.2;
margin-bottom: var(--spacing-m);
}
p {
margin-bottom: var(--spacing-m);
}
a {
color: var(--color-primary-accent);
text-decoration: none;
transition: color var(--transition-fast);
}
a:hover {
color: var(--color-primary-accent-dark);
}"""
"./base/_variables.css" :
"""
/* /assets/css/base/_variables.css */
/* --- :ROOT - CSS SPREMENLJIVKE --- */
:root {
--font-heading: 'Playfair Display', serif;
--font-body: 'Montserrat', sans-serif;
--color-text: #2c3e50; /* Temna, skoraj črna-modra */
--color-background: #fdfdfd;
--color-primary-accent: #4682B4; /* Jekleno modra - profesionalna in umirjena */
--color-primary-accent-dark: #3a6a92;
--color-white: #ffffff;
--color-border: #e0e0e0;
--spacing-xs: 0.25rem;
--spacing-s: 0.5rem;
--spacing-m: 1rem;
--spacing-l: 2rem;
--spacing-xl: 4rem;
--shadow-light: 0 4px 6px rgba(0, 0, 0, 0.05);
--shadow-medium: 0 8px 24px rgba(0, 0, 0, 0.1);
--transition-fast: 0.2s ease-in-out;
--transition-medium: 0.5s ease-in-out;
}"""
"./components/_accordion.css" :
"""
/* /assets/css/components/_accordion.css */
.pricing-accordion {
max-width: 900px;
margin: 0 auto;
}
.accordion-item {
background: var(--color-white);
border: 1px solid var(--color-border);
border-radius: 8px;
margin-bottom: var(--spacing-m);
box-shadow: var(--shadow-light);
transition: box-shadow var(--transition-fast);
}
.accordion-item:hover {
box-shadow: var(--shadow-medium);
}
.accordion-header {
width: 100%;
background: transparent;
border: none;
padding: 1.25rem 1.5rem;
font-family: var(--font-heading);
font-size: 1.25rem;
font-weight: 700;
color: var(--color-text);
text-align: left;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
.accordion-icon {
display: inline-block;
width: 24px;
height: 24px;
position: relative;
transition: transform var(--transition-fast);
}
.accordion-icon::before, .accordion-icon::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 16px;
height: 2px;
background-color: var(--color-primary-accent);
transform: translate(-50%, -50%);
}
.accordion-icon::after { transform: translate(-50%, -50%) rotate(90deg); }
.accordion-item.active .accordion-icon { transform: rotate(135deg); }
.accordion-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.4s ease-out, padding 0.4s ease-out;
}
.accordion-item.active .accordion-content {
padding-bottom: 1.5rem;
}
.price-list { list-style: none; padding: 0 1.5rem; }
.price-item {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: var(--spacing-xs);
padding: var(--spacing-m) 0;
border-bottom: 1px solid var(--color-border);
}
.price-item:last-child { border-bottom: none; }
.service-name, .service-price {
flex-basis: 100%;
text-align: left;
}
.service-name { color: #444; }
.service-price { font-weight: 700; font-size: 1.1rem; color: var(--color-primary-accent); }
.special-pricing-note {
max-width: 900px;
margin: var(--spacing-xl) auto 0 auto;
padding: var(--spacing-l);
text-align: center;
background-color: rgba(70, 130, 180, 0.1);
border: 2px dashed var(--color-primary-accent);
border-radius: 8px;
}
.special-pricing-note h3 { margin-bottom: var(--spacing-s); }
.special-pricing-note p { margin: 0; font-size: 1.2rem; font-weight: 600; }
/* --- MEDIA QUERIES --- */
@media (max-width: 768px) {
.price-item {
flex-direction: column;
align-items: flex-start;
}
.service-price {
text-align: left;
margin-top: var(--spacing-xs);
}
}
@media (min-width: 768px) {
.price-item {
flex-direction: row;
align-items: center;
gap: 0;
}
.service-name { flex-basis: 70%; padding-right: var(--spacing-m); }
.service-price { flex-basis: 30%; text-align: right; }
}"""
"./components/_buttons.css" :
"""
/* /assets/css/components/_buttons.css */
.cta {
display: inline-block;
background-color: var(--color-primary-accent);
color: var(--color-white);
padding: var(--spacing-m) var(--spacing-l);
border-radius: 50px;
font-weight: 700;
margin-top: var(--spacing-m);
transition: background-color var(--transition-fast), transform var(--transition-fast);
box-shadow: var(--shadow-light);
}
.cta:hover,
.cta:focus {
background-color: var(--color-primary-accent-dark);
transform: translateY(-3px);
color: var(--color-white);
}
.nav-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(255, 255, 255, 0.8);
border: 1px solid var(--color-border);
width: 44px;
height: 44px;
font-size: 1.5rem;
border-radius: 50%;
cursor: pointer;
transition: all var(--transition-fast);
z-index: 10;
user-select: none;
color: var(--color-text);
box-shadow: var(--shadow-light);
}
.nav-btn:hover:not(:disabled) {
background: var(--color-white);
transform: translateY(-50%) scale(1.05);
}
.nav-btn.prev {
left: var(--spacing-m);
}
.nav-btn.next {
right: var(--spacing-m);
}
.nav-btn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.contact-form .cta-button {
width: 100%;
border: none;
cursor: pointer;
}
.back-to-blog {
display: inline-block;
margin-top: var(--spacing-xl);
font-weight: 600;
}"""
"./components/_cards.css" :
"""
/* /assets/css/components/_cards.css */
/* --- Stili za kartice storitev --- */
.service-card {
background: var(--color-white);
border-radius: 10px;
box-shadow: var(--shadow-light);
overflow: hidden;
display: flex;
flex-direction: column;
transition: transform var(--transition-fast), box-shadow var(--transition-fast);
border-top: 4px solid var(--color-primary-accent);
}
.service-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-medium);
}
.service-card-image img {
width: 100%;
height: 200px;
object-fit: cover;
display: block;
transition: transform var(--transition-medium);
}
.service-card:hover .service-card-image img {
transform: scale(1.05);
}
.service-card-content {
padding: var(--spacing-l) 1.5rem 1.5rem 1.5rem;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.service-card h3 {
font-size: 1.25rem;
color: var(--color-text);
margin-bottom: var(--spacing-m);
}
.service-card p {
font-size: 0.95rem;
color: #555;
flex-grow: 1;
margin-bottom: var(--spacing-m);
}
.service-card-link {
font-weight: 600;
color: var(--color-primary-accent);
align-self: flex-start;
position: relative;
padding-bottom: var(--spacing-xs);
}
.service-card-link::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0%;
height: 2px;
background-color: var(--color-primary-accent);
transition: width var(--transition-fast);
}
.service-card-link:hover::after {
width: 100%;
}
/* --- Stili za kartice bloga --- */
.blog-card {
background: var(--color-white);
border-radius: 10px;
box-shadow: var(--shadow-light);
overflow: hidden;
transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
.blog-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-medium);
}
.card-link-wrapper { display: block; color: inherit; text-decoration: none; }
.blog-card-image { overflow: hidden; }
.blog-card-image img { width: 100%; height: 220px; object-fit: cover; display: block; transition: transform var(--transition-medium); }
.blog-card:hover .blog-card-image img { transform: scale(1.05); }
.blog-card-content { padding: 1.5rem; }
.blog-card-title { font-size: 1.3rem; color: var(--color-text); margin-bottom: var(--spacing-m); line-height: 1.3; }
.blog-card-excerpt { font-size: 0.95rem; color: #555; margin-bottom: var(--spacing-m); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.blog-card-link { font-weight: 600; color: var(--color-primary-accent); position: relative; padding-bottom: var(--spacing-xs); display: inline-block; }
.blog-card-link::after { content: ''; position: absolute; bottom: 0; left: 0; width: 0%; height: 2px; background-color: var(--color-primary-accent); transition: width var(--transition-fast); }
.blog-card:hover .blog-card-link::after { width: 100%; }"""
"./components/_contact-form.css" :
"""
/* /assets/css/components/_contact-form.css */
.contact-form-wrapper {
background: var(--color-white);
padding: var(--spacing-l);
border-radius: 8px;
box-shadow: var(--shadow-light);
}
.contact-form .form-group {
margin-bottom: 1.5rem;
}
.contact-form label {
display: block;
margin-bottom: var(--spacing-s);
font-weight: 600;
}
.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form textarea {
width: 100%;
padding: 0.8rem 1rem;
border: 1px solid var(--color-border);
border-radius: 5px;
font-family: var(--font-body);
font-size: 1rem;
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.contact-form input[type="text"]:focus,
.contact-form input[type="email"]:focus,
.contact-form textarea:focus {
outline: none;
border-color: var(--color-primary-accent);
box-shadow: 0 0 0 3px rgba(70, 130, 180, 0.2);
}
.contact-form textarea {
resize: vertical;
min-height: 120px;
}
.form-message {
margin-top: var(--spacing-m);
padding: var(--spacing-m);
border-radius: 5px;
text-align: center;
font-weight: 600;
transition: opacity 0.3s ease-in-out, max-height 0.3s ease-in-out, margin 0.3s ease-in-out, padding 0.3s ease-in-out;
opacity: 0;
max-height: 0;
overflow: hidden;
padding-top: 0;
padding-bottom: 0;
margin-top: 0;
}
.form-message.visible {
opacity: 1;
max-height: 100px;
padding-top: var(--spacing-m);
padding-bottom: var(--spacing-m);
margin-top: var(--spacing-m);
}
.form-message.success {
background-color: rgba(70, 180, 130, 0.1);
color: #3a926a;
border: 1px solid #46B482;
}
.form-message.error {
background-color: rgba(180, 70, 70, 0.1);
color: #b44646;
border: 1px solid #b44646;
}"""
"./components/_footer.css" :
"""
/* /assets/css/components/_footer.css */
/* --- NOGA --- */
.main-footer-bar {
padding: var(--spacing-l) var(--spacing-l);
text-align: center;
font-size: 0.9rem;
color: #777;
background-color: #f1f1f1;
}
body:not(.homepage) .main-footer-bar {
margin-top: var(--spacing-xl);
}"""
"./components/_header.css" :
"""
/* /assets/css/components/_header.css */
/* --- GLAVA IN NAVIGACIJA --- */
.main-header {
background-color: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
box-shadow: var(--shadow-light);
border-bottom: 1px solid var(--color-border);
position: relative; /* Potrebno za z-index mobilnega menija */
z-index: 1000;
}
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-m) var(--spacing-l);
max-width: 1600px;
margin: 0 auto;
}
.logo a {
font-family: var(--font-heading);
font-weight: 800;
font-size: 1.2rem;
color: var(--color-text);
letter-spacing: 0.5px;
}
/* MOBILNA NAVIGACIJA: Osnovni stili */
.main-nav {
display: none; /* Privzeto skrito za mobilne naprave */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(253, 253, 253, 0.98);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
flex-direction: column;
justify-content: center;
align-items: center;
transform: translateY(-100%);
transition: transform var(--transition-medium);
}
.main-nav.open { /* Uporabljamo razred 'open' za aktivacijo mobilnega menija */
display: flex;
transform: translateY(0);
}
.main-nav ul {
list-style: none;
display: flex;
flex-direction: column;
gap: 1.5rem;
align-items: center;
text-align: center;
padding: 0;
}
.main-nav a {
color: var(--color-text);
font-weight: 600;
font-size: 1.2rem;
padding: var(--spacing-s) 0;
position: relative;
letter-spacing: 0.5px;
}
.main-nav a::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 2px;
background-color: var(--color-primary-accent);
transition: width var(--transition-fast);
}
.main-nav a:hover::after,
.main-nav a.active::after {
width: 100%;
}
.main-nav a.nav-cta {
background-color: var(--color-primary-accent);
color: var(--color-white);
padding: var(--spacing-s) var(--spacing-m);
border-radius: 50px;
transition: background-color var(--transition-fast), transform var(--transition-fast);
}
.main-nav a.nav-cta:hover {
background-color: var(--color-primary-accent-dark);
color: var(--color-white);
transform: translateY(-2px);
}
.main-nav a.nav-cta:hover::after {
width: 0;
}
/* --- MOBILNA NAVIGACIJA (HAMBURGER) --- */
.mobile-nav-toggle {
display: block; /* Hamburger gumb je privzeto viden na mobilnih napravah */
background: none;
border: none;
cursor: pointer;
z-index: 1001; /* Višji od menija, da je vedno na vrhu */
padding: var(--spacing-s);
position: relative;
}
.hamburger {
display: block;
position: relative;
width: 24px;
height: 2px;
background: var(--color-text);
transition: all 0.25s ease-in-out;
}
.hamburger::before, .hamburger::after {
content: '';
position: absolute;
left: 0;
width: 100%;
height: 2px;
background: var(--color-text);
transition: all 0.25s ease-in-out;
}
.hamburger::before { top: -8px; }
.hamburger::after { bottom: -8px; }
/* --- MEDIA QUERIES --- */
@media (max-width: 991px) {
.mobile-nav-toggle {
display: block; /* Prikaže hamburger gumb na mobilnih napravah */
}
/* KODA ZA AKTIVACIJO MOBILNEGA MENIJA IN HAMBURGER IKONE NA MOBILNIH NAPRAVAH */
/* Hamburger se spremeni v X, ko je meni odprt (glede na razred 'open' na toggle gumbu) */
.mobile-nav-toggle.open .hamburger {
background: transparent;
}
.mobile-nav-toggle.open .hamburger::before {
transform: rotate(45deg);
top: 0;
}
.mobile-nav-toggle.open .hamburger::after {
transform: rotate(-45deg);
bottom: 0;
}
}
@media (min-width: 992px) {
/* Stili za namizje */
.mobile-nav-toggle {
display: none; /* Skrije hamburger gumb na namizju */
}
.main-nav {
display: flex; /* Prikaže navigacijo kot flex kontejner */
position: static; /* Odstrani fiksno pozicioniranje */
height: auto;
width: auto;
background-color: transparent;
backdrop-filter: none; /* Odstrani zameglitev na namizju */
-webkit-backdrop-filter: none; /* Odstrani zameglitev na namizju */
transform: none; /* Odstrani transformacijo */
flex-direction: row; /* Elementi menija v vrsto */
align-items: center;
}
.main-nav ul {
flex-direction: row; /* Elementi seznama v vrsto */
gap: 1.8rem;
}
.main-nav a {
font-size: 0.9rem; /* Manjša pisava za namizje */
padding: var(--spacing-s) 0; /* Dodano padding */
}
.main-nav a.nav-cta {
padding: var(--spacing-s) var(--spacing-m);
}
}"""
"./components/_slider.css" :
"""
/* /assets/css/components/_slider.css */
/* ================================================= */
/* === STILI ZA DRSNIK NA DOMAČI STRANI === */
/* ================================================= */
.slider {
position: relative;
max-width: 1200px;
margin: var(--spacing-l) auto;
background: var(--color-white);
padding: var(--spacing-l);
border-radius: 1rem;
overflow: hidden;
box-shadow: var(--shadow-medium);
}
.slide {
display: none;
}
.slide.active {
display: block;
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.slide-content {
display: flex;
align-items: center;
gap: var(--spacing-xl);
}
.slide-image {
flex: 1 1 50%;
}
.slide-image img {
width: 100%;
height: auto;
display: block;
border-radius: 0.5rem; /* Rahlo zaobljeni robovi na sliki */
}
.slide-text {
flex: 1 1 50%;
}
.slide-text h2 {
font-size: clamp(1.8rem, 4vw, 2.5rem);
color: var(--color-primary-accent);
margin-bottom: var(--spacing-m);
}
.slide-text p {
margin-bottom: var(--spacing-m);
}
/* --- MEDIA QUERIES --- */
@media (max-width: 768px) {
/* Spremembe za tablice in manjše naprave */
.slide-content {
flex-direction: column;
text-align: center;
}
.slide-text h2 {
font-size: 1.8rem;
}
}"""
"./layout/_grids.css" :
"""
/* /assets/css/layout/_grids.css */
.about-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
align-items: flex-start;
}
.image-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
margin-bottom: var(--spacing-xl);
}
.services-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
}
.blog-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
}
.contact-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-xl);
}
/* --- MEDIA QUERIES --- */
@media (max-width: 768px) {
.image-grid, .services-grid, .blog-grid, .contact-grid {
grid-template-columns: 1fr;
}
}
@media (min-width: 768px) {
/* Stili za večje tablice */
.image-grid { grid-template-columns: 1fr 1fr; }
.services-grid { grid-template-columns: repeat(2, 1fr); }
.blog-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 992px) {
/* Stili za namizje */
.about-grid {
grid-template-columns: 1fr 2fr;
gap: var(--spacing-xl);
}
.services-grid, .blog-grid {
grid-template-columns: repeat(3, 1fr);
gap: var(--spacing-xl);
}
.contact-grid {
grid-template-columns: 1fr 1fr;
align-items: flex-start;
}
}"""
"./layout/_structure.css" :
"""
/* /assets/css/layout/_structure.css */
/* === OSNOVNA STRUKTURA PODSTRANI === */
.page-main-content {
padding-top: var(--spacing-xl);
padding-bottom: var(--spacing-xl);
min-height: calc(100vh - 80px - 150px);
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 0 var(--spacing-l);
}
.page-title {
font-size: clamp(2.5rem, 6vw, 4rem);
text-align: center;
margin-bottom: var(--spacing-xl);
color: var(--color-primary-accent);
}
.section-title {
font-size: clamp(1.5rem, 4vw, 2rem);
margin-top: var(--spacing-l);
margin-bottom: var(--spacing-m);
color: var(--color-text);
border-left: 4px solid var(--color-primary-accent);
padding-left: var(--spacing-m);
}
.intro-text {
font-size: 1.25rem;
font-style: italic;
font-weight: 500;
line-height: 1.6;
margin-bottom: var(--spacing-l);
color: #555;
}
.page-subtitle {
font-size: clamp(1.1rem, 3vw, 1.4rem);
text-align: center;
max-width: 800px;
margin: 0 auto var(--spacing-xl) auto;
color: #555;
}
.text-section {
margin-bottom: var(--spacing-l);
}
/* === SPLOŠNI STRUKTURNI ELEMENTI === */
.about-image {
width: 100%;
max-width: 400px;
margin: 0 auto;
position: static;
}
.about-image img {
width: 100%;
height: auto;
border-radius: 10px;
box-shadow: var(--shadow-medium);
}
.grid-image {
width: 100%;
min-height: 250px;
background-size: cover;
background-position: center;
border-radius: 10px;
box-shadow: var(--shadow-medium);
transition: transform var(--transition-medium), box-shadow var(--transition-medium);
}
.grid-image:hover {
transform: scale(1.03);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
}
.highlight-quote {
margin: var(--spacing-l) auto;
padding: var(--spacing-l);
border-left: 5px solid var(--color-primary-accent);
background-color: rgba(70, 130, 180, 0.05);
border-radius: 0 8px 8px 0;
}
.highlight-quote p {
font-size: 1.1rem;
font-style: italic;
font-weight: 500;
margin-bottom: var(--spacing-m);
}
.highlight-quote cite {
display: block;
text-align: right;
font-style: normal;
font-weight: 600;
}
.concluding-statement {
text-align: center;
padding: var(--spacing-l);
margin: var(--spacing-xl) 0;
border: 1px solid var(--color-border);
border-radius: 8px;
background-color: var(--color-white);
box-shadow: var(--shadow-light);
}
.concluding-statement p {
margin-bottom: 0;
font-size: 1.1rem;
line-height: 1.8;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.content-cta {
text-align: center;
margin-top: var(--spacing-xl);
}
.page-hero {
padding: var(--spacing-l) 0;
text-align: center;
background-color: rgba(70, 130, 180, 0.05);
margin-bottom: var(--spacing-xl);
}
.page-hero .page-title {
margin-bottom: var(--spacing-m);
}
.page-hero .page-subtitle {
font-size: 1.1rem;
max-width: 700px;
margin: 0 auto;
color: #555;
font-style: normal;
}
/* --- KONTAKT IN ZEMLJEVID --- */
.contact-details {
background-color: rgba(221, 226, 229, 0.2);
padding: var(--spacing-l);
border-radius: 8px;
}
.contact-info-item { margin-bottom: 1.5rem; }
.contact-info-item .info-label { display: block; font-size: 0.9rem; font-weight: 600; color: #777; margin-bottom: var(--spacing-xs); }
.contact-info-item .info-data { font-size: 1.1rem; margin: 0; }
.contact-info-item .info-data a { word-break: break-all; }
.map-placeholder { width: 100%; height: 300px; border-radius: 8px; overflow: hidden; margin-top: var(--spacing-l); background-color: #e9e9e9; box-shadow: inset 0 2px 4px rgba(0,0,0,0.06); }
.map-placeholder iframe { width: 100%; height: 100%; border: 0; }
/* --- UTILNOSTI --- */
.animate-on-scroll {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
}
.animate-on-scroll.is-visible {
opacity: 1;
transform: translateY(0);
}
/* --- MEDIA QUERIES --- */
@media (max-width: 768px) {
.grid-image { min-height: 250px; }
}
@media (min-width: 768px) {
.grid-image { min-height: 350px; }
}
@media (min-width: 992px) {
.about-image {
max-width: 100%;
position: sticky;
top: calc(var(--spacing-l) + 80px); /* Odmik + višina glave */
}
}"""
"./main.css" :
"""
/* /assets/css/main.css */
/* Ta datoteka služi kot glavna vstopna točka in uvaža vse ostale CSS parciale. */
/* 1. Base Styles - Osnovni stili, spremenljivke in tipografija */
@import url('base/_variables.css');
@import url('base/_reset.css');
@import url('base/_typography.css');
/* 2. Layout Styles - Strukturni elementi in mreže */
@import url('layout/_structure.css');
@import url('layout/_grids.css');
/* 3. Components - Ponovno uporabljivi gradniki (gumbi, kartice, itd.) */
@import url('components/_header.css');
@import url('components/_footer.css');
@import url('components/_slider.css');
@import url('components/_buttons.css');
@import url('components/_cards.css');
@import url('components/_accordion.css');
@import url('components/_contact-form.css');
/* 4. Page-Specific Styles - Stili za specifične tipe strani */
@import url('pages/_article.css');"""
"./pages/_article.css" :
"""
/* /assets/css/pages/_article.css */
/* === STILI ZA PODSTRANI POSAMEZNIH STORITEV === */
.service-hero {
padding: var(--spacing-xl) 0;
text-align: center;
background-color: #f7f9fa;
border-bottom: 1px solid var(--color-border);
}
.service-hero .page-title {
color: var(--color-text);
}
.service-content-wrapper {
max-width: 800px;
margin: var(--spacing-xl) auto 0 auto;
}
.service-content-wrapper .section-title {
margin-top: var(--spacing-xl);
}
.service-content-wrapper p {
font-size: 1.05rem;
line-height: 1.8;
}
.service-content-wrapper strong {
color: var(--color-primary-accent-dark);
}
.service-tagline {
font-size: 1.1rem;
font-weight: 600;
text-align: center;
text-transform: uppercase;
letter-spacing: 1px;
margin: var(--spacing-xl) 0;
color: var(--color-primary-accent);
}
/* === STILI ZA STRAN POSAMEZNEGA ČLANKA (BLOG) === */
.article-header {
text-align: center;
margin-bottom: var(--spacing-xl);
}
.article-header .page-title {
margin-bottom: var(--spacing-m);
}
.article-meta {
font-size: 0.9rem;
color: #777;
margin-bottom: var(--spacing-l);
}
.article-hero-image {
width: 100%;
height: 250px;
background-size: cover;
background-position: center;
border-radius: 10px;
margin-bottom: var(--spacing-xl);
box-shadow: var(--shadow-medium);
}
.article-content {
max-width: 750px;
margin: 0 auto;
}
.article-content h2,
.article-content h3 {
margin-top: var(--spacing-l);
margin-bottom: var(--spacing-m);
font-size: 1.5rem;
color: var(--color-primary-accent-dark);
}
.article-content p {
font-size: 1.05rem;
line-height: 1.8;
margin-bottom: 1.5rem;
}
.article-content ul {
list-style-position: inside;
padding-left: 1rem;
margin-bottom: 1.5rem;
}
.article-content li {
margin-bottom: 0.75rem;
}
.article-content blockquote {
margin: var(--spacing-l) 0;
padding-left: var(--spacing-l);
border-left: 4px solid var(--color-primary-accent);
font-style: italic;
font-size: 1.2rem;
color: #555;
}
.article-content strong {
color: var(--color-text);
}
/* --- MEDIA QUERIES --- */
@media (max-width: 768px) {
.article-hero-image {
height: 250px;
}
}
@media (min-width: 768px) {
.article-hero-image {
height: 350px;
}
}
@media (min-width: 992px) {
.article-hero-image {
height: 400px;
}
}"""
"""
"./assets/css/components/_accordion.css" :
"""
/* /assets/css/components/_accordion.css */
.pricing-accordion {
max-width: 900px;
margin: 0 auto;
}
.accordion-item {
background: var(--color-white);
border: 1px solid var(--color-border);
border-radius: 8px;
margin-bottom: var(--spacing-m);
box-shadow: var(--shadow-light);
transition: box-shadow var(--transition-fast);
}
.accordion-item:hover {
box-shadow: var(--shadow-medium);
}
.accordion-header {
width: 100%;
background: transparent;
border: none;
padding: 1.25rem 1.5rem;
font-family: var(--font-heading);
font-size: 1.25rem;
font-weight: 700;
color: var(--color-text);
text-align: left;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
.accordion-icon {
display: inline-block;
width: 24px;
height: 24px;
position: relative;
transition: transform var(--transition-fast);
}
.accordion-icon::before, .accordion-icon::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 16px;
height: 2px;
background-color: var(--color-primary-accent);
transform: translate(-50%, -50%);
}
.accordion-icon::after { transform: translate(-50%, -50%) rotate(90deg); }
.accordion-item.active .accordion-icon { transform: rotate(135deg); }
.accordion-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.4s ease-out, padding 0.4s ease-out;
}
.accordion-item.active .accordion-content {
padding-bottom: 1.5rem;
}
.price-list { list-style: none; padding: 0 1.5rem; }
.price-item {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: var(--spacing-xs);
padding: var(--spacing-m) 0;
border-bottom: 1px solid var(--color-border);
}
.price-item:last-child { border-bottom: none; }
.service-name, .service-price {
flex-basis: 100%;
text-align: left;
}
.service-name { color: #444; }
.service-price { font-weight: 700; font-size: 1.1rem; color: var(--color-primary-accent); }
.special-pricing-note {
max-width: 900px;
margin: var(--spacing-xl) auto 0 auto;
padding: var(--spacing-l);
text-align: center;
background-color: rgba(8, 4, 252, 0.1); /* SPREMEMBA: Ujemanje z novo barvo */
border: 2px dashed var(--color-primary-accent);
border-radius: 8px;
}
.special-pricing-note h3 { margin-bottom: var(--spacing-s); }
.special-pricing-note p { margin: 0; font-size: 1.2rem; font-weight: 600; }
/* --- MEDIA QUERIES --- */
@media (max-width: 768px) {
.price-item {
flex-direction: column;
align-items: flex-start;
}
.service-price {
text-align: left;
margin-top: var(--spacing-xs);
}
}
@media (min-width: 768px) {
.price-item {
flex-direction: row;
align-items: center;
gap: 0;
}
.service-name { flex-basis: 70%; padding-right: var(--spacing-m); }
.service-price { flex-basis: 30%; text-align: right; }
}"""
"./assets/css/components/_buttons.css" :
"""
/* /assets/css/components/_buttons.css */
.cta {
display: inline-block;
background-color: var(--color-primary-accent);
color: var(--color-white);
padding: var(--spacing-m) var(--spacing-l);
border-radius: 50px;
font-weight: 700;
margin-top: var(--spacing-m);
transition: background-color var(--transition-fast), transform var(--transition-fast);
box-shadow: var(--shadow-light);
}
.cta:hover,
.cta:focus {
background-color: var(--color-primary-accent-dark);
transform: translateY(-3px);
color: var(--color-white);
}
.nav-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(255, 255, 255, 0.8);
border: 1px solid var(--color-border);
width: 44px;
height: 44px;
font-size: 1.5rem;
border-radius: 50%;
cursor: pointer;
transition: all var(--transition-fast);
z-index: 10;
user-select: none;
color: var(--color-text);
box-shadow: var(--shadow-light);
}
.nav-btn:hover:not(:disabled) {
background: var(--color-white);
transform: translateY(-50%) scale(1.05);
}
.nav-btn.prev {
left: var(--spacing-m);
}
.nav-btn.next {
right: var(--spacing-m);
}
.nav-btn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.contact-form .cta-button {
width: 100%;
border: none;
cursor: pointer;
}
.back-to-blog {
display: inline-block;
margin-top: var(--spacing-xl);
font-weight: 600;
}
/* === GUMB ZA NA VRH (DODANO) === */
.back-to-top-btn {
position: fixed;
bottom: var(--spacing-l);
right: var(--spacing-l);
width: 50px;
height: 50px;
background-color: var(--color-primary-accent);
color: var(--color-white);
border: none;
border-radius: 50%;
box-shadow: var(--shadow-medium);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
line-height: 1;
z-index: 1000;
text-decoration: none;
/* Stanje za animacijo */
opacity: 0;
visibility: hidden;
transform: translateY(20px);
transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out, transform 0.3s ease-in-out;
}
.back-to-top-btn:hover {
background-color: var(--color-primary-accent-dark);
color: var(--color-white);
}
.back-to-top-btn.visible {
opacity: 1;
visibility: visible;
transform: translateY(0);
}"""
"./assets/css/components/_cards.css" :
"""
/* /assets/css/components/_cards.css */
/* --- Stili za kartice storitev --- */
.service-card {
background: var(--color-white);
border-radius: 10px;
box-shadow: var(--shadow-light);
overflow: hidden;
display: flex;
flex-direction: column;
transition: transform var(--transition-fast), box-shadow var(--transition-fast);
border-top: 4px solid var(--color-primary-accent);
}
.service-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-medium);
}
.service-card-image img {
width: 100%;
height: 200px;
object-fit: cover;
display: block;
transition: transform var(--transition-medium);
}
.service-card:hover .service-card-image img {
transform: scale(1.05);
}
.service-card-content {
padding: var(--spacing-l) 1.5rem 1.5rem 1.5rem;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.service-card h3 {
font-size: 1.25rem;
color: var(--color-text);
margin-bottom: var(--spacing-m);
}
.service-card p {
font-size: 0.95rem;
color: #555;
flex-grow: 1;
margin-bottom: var(--spacing-m);
}
.service-card-link {
font-weight: 600;
color: var(--color-primary-accent);
align-self: flex-start;
position: relative;
padding-bottom: var(--spacing-xs);
}
.service-card-link::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0%;
height: 2px;
background-color: var(--color-primary-accent);
transition: width var(--transition-fast);
}
.service-card-link:hover::after {
width: 100%;
}
/* --- Stili za kartice bloga --- */
.blog-card {
background: var(--color-white);
border-radius: 10px;
box-shadow: var(--shadow-light);
overflow: hidden;
transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
.blog-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-medium);
}
.card-link-wrapper { display: block; color: inherit; text-decoration: none; }
.blog-card-image { overflow: hidden; }
.blog-card-image img { width: 100%; height: 220px; object-fit: cover; display: block; transition: transform var(--transition-medium); }
.blog-card:hover .blog-card-image img { transform: scale(1.05); }
.blog-card-content { padding: 1.5rem; }
.blog-card-title { font-size: 1.3rem; color: var(--color-text); margin-bottom: var(--spacing-m); line-height: 1.3; }
.blog-card-excerpt { font-size: 0.95rem; color: #555; margin-bottom: var(--spacing-m); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.blog-card-link { font-weight: 600; color: var(--color-primary-accent); position: relative; padding-bottom: var(--spacing-xs); display: inline-block; }
.blog-card-link::after { content: ''; position: absolute; bottom: 0; left: 0; width: 0%; height: 2px; background-color: var(--color-primary-accent); transition: width var(--transition-fast); }
.blog-card:hover .blog-card-link::after { width: 100%; }"""
"./assets/css/components/_contact-form.css" :
"""
/* /assets/css/components/_contact-form.css */
.contact-form-wrapper {
background: var(--color-white);
padding: var(--spacing-l);
border-radius: 8px;
box-shadow: var(--shadow-light);
}
.contact-form .form-group {
margin-bottom: 1.5rem;
}
.contact-form label {
display: block;
margin-bottom: var(--spacing-s);
font-weight: 600;
}
.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form textarea {
width: 100%;
padding: 0.8rem 1rem;
border: 1px solid var(--color-border);
border-radius: 5px;
font-family: var(--font-body);
font-size: 1rem;
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.contact-form input[type="text"]:focus,
.contact-form input[type="email"]:focus,
.contact-form textarea:focus {
outline: none;
border-color: var(--color-primary-accent);
box-shadow: 0 0 0 3px rgba(8, 4, 252, 0.2); /* SPREMEMBA: Ujemanje z novo barvo */
}
.contact-form textarea {
resize: vertical;
min-height: 120px;
}
.form-message {
margin-top: var(--spacing-m);
padding: var(--spacing-m);
border-radius: 5px;
text-align: center;
font-weight: 600;
transition: opacity 0.3s ease-in-out, max-height 0.3s ease-in-out, margin 0.3s ease-in-out, padding 0.3s ease-in-out;
opacity: 0;
max-height: 0;
overflow: hidden;
padding-top: 0;
padding-bottom: 0;
margin-top: 0;
}
.form-message.visible {
opacity: 1;
max-height: 100px;
padding-top: var(--spacing-m);
padding-bottom: var(--spacing-m);
margin-top: var(--spacing-m);
}
.form-message.success {
background-color: rgba(70, 180, 130, 0.1);
color: #3a926a;
border: 1px solid #46B482;
}
.form-message.error {
background-color: rgba(180, 70, 70, 0.1);
color: #b44646;
border: 1px solid #b44646;
}
/* === STILI ZA ŠTEVEC ZNAKOV (DODANO) === */
.char-counter {
text-align: right;
font-size: 0.85rem;
color: #777;
margin-top: var(--spacing-s);
transition: color 0.3s ease-in-out;
}
.char-counter.warning {
color: #d98d00; /* Oranžna barva za opozorilo */
font-weight: 600;
}
.char-counter.limit {
color: #b44646; /* Rdeča barva za preseženo omejitev */
font-weight: 600;
}"""
"./assets/css/components/_footer.css" :
"""
/* /assets/css/components/_footer.css */
/* --- NOGA --- */
.main-footer-bar {
padding: var(--spacing-l) var(--spacing-l);
text-align: center;
font-size: 0.9rem;
color: #777;
background-color: #f1f1f1;
}
body:not(.homepage) .main-footer-bar {
margin-top: var(--spacing-xl);
}"""
"./assets/css/components/_header.css" :
"""
/* /assets/css/components/_header.css */
/* --- GLAVA IN NAVIGACIJA --- */
.main-header {
background-color: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
box-shadow: var(--shadow-light);
border-bottom: 1px solid var(--color-border);
position: relative; /* Potrebno za z-index mobilnega menija */
z-index: 1000;
}
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-m) var(--spacing-l);
max-width: 1600px;
margin: 0 auto;
}
.logo a {
font-family: var(--font-heading);
font-weight: 800;
font-size: 1.2rem;
color: var(--color-text);
letter-spacing: 0.5px;
}
/* MOBILNA NAVIGACIJA: Osnovni stili */
.main-nav {
display: none; /* Privzeto skrito za mobilne naprave */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(253, 253, 253, 0.98);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
flex-direction: column;
justify-content: center;
align-items: center;
transform: translateY(-100%);
transition: transform var(--transition-medium);
}
.main-nav.open { /* Uporabljamo razred 'open' za aktivacijo mobilnega menija */
display: flex;
transform: translateY(0);
}
.main-nav ul {
list-style: none;
display: flex;
flex-direction: column;
gap: 1.5rem;
align-items: center;
text-align: center;
padding: 0;
}
.main-nav a {
color: var(--color-text);
font-weight: 600;
font-size: 1.2rem;
padding: var(--spacing-s) 0;
position: relative;
letter-spacing: 0.5px;
}
.main-nav a::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 2px;
background-color: var(--color-primary-accent);
transition: width var(--transition-fast);
}
.main-nav a:hover::after,
.main-nav a.active::after {
width: 100%;
}
.main-nav a.nav-cta {
background-color: var(--color-primary-accent);
color: var(--color-white);
padding: var(--spacing-s) var(--spacing-m);
border-radius: 50px;
transition: background-color var(--transition-fast), transform var(--transition-fast);
}
.main-nav a.nav-cta:hover {
background-color: var(--color-primary-accent-dark);
color: var(--color-white);
transform: translateY(-2px);
}
.main-nav a.nav-cta:hover::after {
width: 0;
}
/* --- MOBILNA NAVIGACIJA (HAMBURGER) --- */
.mobile-nav-toggle {
display: block; /* Hamburger gumb je privzeto viden na mobilnih napravah */
background: none;
border: none;
cursor: pointer;
z-index: 1001; /* Višji od menija, da je vedno na vrhu */
padding: var(--spacing-s);
position: relative;
}
.hamburger {
display: block;
position: relative;
width: 24px;
height: 2px;
background: var(--color-text);
transition: all 0.25s ease-in-out;
}
.hamburger::before, .hamburger::after {
content: '';
position: absolute;
left: 0;
width: 100%;
height: 2px;
background: var(--color-text);
transition: all 0.25s ease-in-out;
}
.hamburger::before { top: -8px; }
.hamburger::after { bottom: -8px; }
/* --- MEDIA QUERIES --- */
@media (max-width: 991px) {
.mobile-nav-toggle {
display: block; /* Prikaže hamburger gumb na mobilnih napravah */
}
/* KODA ZA AKTIVACIJO MOBILNEGA MENIJA IN HAMBURGER IKONE NA MOBILNIH NAPRAVAH */
/* Hamburger se spremeni v X, ko je meni odprt (glede na razred 'open' na toggle gumbu) */
.mobile-nav-toggle.open .hamburger {
background: transparent;
}
.mobile-nav-toggle.open .hamburger::before {
transform: rotate(45deg);
top: 0;
}
.mobile-nav-toggle.open .hamburger::after {
transform: rotate(-45deg);
bottom: 0;
}
}
@media (min-width: 992px) {
/* Stili za namizje */
.mobile-nav-toggle {
display: none; /* Skrije hamburger gumb na namizju */
}
.main-nav {
display: flex; /* Prikaže navigacijo kot flex kontejner */
position: static; /* Odstrani fiksno pozicioniranje */
height: auto;
width: auto;
background-color: transparent;
backdrop-filter: none; /* Odstrani zameglitev na namizju */
-webkit-backdrop-filter: none; /* Odstrani zameglitev na namizju */
transform: none; /* Odstrani transformacijo */
flex-direction: row; /* Elementi menija v vrsto */
align-items: center;
}
.main-nav ul {
flex-direction: row; /* Elementi seznama v vrsto */
gap: 1.8rem;
}
.main-nav a {
font-size: 0.9rem; /* Manjša pisava za namizje */
padding: var(--spacing-s) 0; /* Dodano padding */
}
.main-nav a.nav-cta {
padding: var(--spacing-s) var(--spacing-m);
}
}"""
"./assets/css/components/_slider.css" :
"""
/* /assets/css/components/_slider.css */
/* ================================================= */
/* === STILI ZA DRSNIK NA DOMAČI STRANI === */
/* ================================================= */
.slider {
position: relative;
max-width: 1200px;
margin: var(--spacing-l) auto;
background: var(--color-white);
padding: var(--spacing-l);
border-radius: 1rem;
overflow: hidden;
box-shadow: var(--shadow-medium);
}
.slide {
display: none;
}
.slide.active {
display: block;
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.slide-content {
display: flex;
align-items: center;
gap: var(--spacing-xl);
}
.slide-image {
flex: 1 1 50%;
}
.slide-image img {
width: 100%;
height: auto;
display: block;
border-radius: 0.5rem; /* Rahlo zaobljeni robovi na sliki */
}
.slide-text {
flex: 1 1 50%;
}
.slide-text h2 {
font-size: clamp(1.8rem, 4vw, 2.5rem);
color: var(--color-primary-accent);
margin-bottom: var(--spacing-m);
}
.slide-text p {
margin-bottom: var(--spacing-m);
}
/* === SPREMENJENI STILI ZA PORTRET NA PRVEM SLAJDU === */
.slide-portrait {
float: right;
width: 250px; /* SPREMEMBA: Velikost usklajena s kontaktno stranjo */
height: 250px; /* SPREMEMBA: Velikost usklajena s kontaktno stranjo */
margin: 0 0 var(--spacing-m) var(--spacing-l); /* Odmik od besedila */
border-radius: 10px; /* SPREMEMBA: Zaobljeni robovi, kot na kontaktni strani */
overflow: hidden;
box-shadow: var(--shadow-medium); /* Uporaba obstoječe sence */
border: none; /* Odstranjen bel rob */
}
.slide-portrait img {
width: 100%;
height: 100%;
object-fit: cover; /* Zagotovi, da slika lepo zapolni kvadrat brez popačenja */
display: block;
}
/* --- MEDIA QUERIES --- */
@media (max-width: 768px) {
/* Spremembe za tablice in manjše naprave */
.slide-content {
flex-direction: column;
text-align: center;
}
.slide-text h2 {
font-size: 1.8rem;
}
/* Prilagoditve za portret na mobilnih napravah */
.slide-portrait {
float: none; /* Odstranimo float, da se slika centrira */
margin: 0 auto var(--spacing-l) auto; /* Centriramo portret in mu dodamo odmik spodaj */
width: 200px; /* SPREMEMBA: Povečana velikost za boljšo vidljivost */
height: 200px; /* SPREMEMBA: Povečana velikost za boljšo vidljivost */
}
}"""
"./assets/css/export_code.sh" :
"""
#!/bin/bash
# Nastavitev imena izhodne datoteke
OUTPUT_FILE="code_export.txt"
# Odstrani izhodno datoteko, če že obstaja, da začnemo s čisto datoteko
if [ -f "$OUTPUT_FILE" ]; then
rm "$OUTPUT_FILE"
fi
# Poišči vse datoteke, razen skritih datotek in določenih map (npr. node_modules).
# Dodane so izjeme za slike, videoposnetke, PDF-je, arhive in druge binarne datoteke
# neposredno v ukaz 'find' za boljšo zmogljivost.
find . -type f \
-not -path "*/\.*" \
-not -path "*node_modules*" \
-not -path "*vendor*" \
-not -path "*dist*" \
-not -path "*build*" \
-not -name "*.jpg" -not -name "*.jpeg" \
-not -name "*.JPG" -not -name "*.JPEG" \
-not -name "*.png" -not -name "*.gif" \
-not -name "*.bmp" -not -name "*.tiff" \
-not -name "*.svg" -not -name "*.ico" \
-not -name "*.webp" \
-not -name "*.mp4" -not -name "*.mov" \
-not -name "*.avi" -not -name "*.mkv" \
-not -name "*.webm" \
-not -name "*.mp3" -not -name "*.wav" \
-not -name "*.ogg" -not -name "*.flac" \
-not -name "*.pdf" \
-not -name "*.zip" \
-not -name "*.tar" \
-not -name "*.gz" \
-not -name "*.bz2" \
-not -name "*.rar" \
-not -name "*.7z" \
-not -name "*.doc" -not -name "*.docx" \
-not -name "*.xls" -not -name "*.xlsx" \
-not -name "*.ppt" -not -name "*.pptx" \
-not -name "*.eot" -not -name "*.ttf" \
-not -name "*.woff" -not -name "*.woff2" \
| sort | while read -r file; do
# Preskoči samo izhodno datoteko in to skripto
if [[ "$file" == "./$OUTPUT_FILE" || "$file" == "./export_code.sh" ]]; then
continue
fi
# Dodatna varnostna preverba: preskoči binarne datoteke, ki jih 'find' morda ni ujel
if file "$file" | grep -q "binary"; then
continue
fi
# Dodaj ime datoteke in njeno vsebino v izhodno datoteko
echo "\"$file\" : " >> "$OUTPUT_FILE"
echo "\"\"\"" >> "$OUTPUT_FILE"
cat "$file" >> "$OUTPUT_FILE"
echo "\"\"\"" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
done
echo "Izvoz kode končan. Vsebina je shranjena v datoteko $OUTPUT_FILE""""
"./assets/css/layout/_grids.css" :
"""
/* /assets/css/layout/_grids.css */
.about-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
align-items: flex-start;
}
.image-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
margin-bottom: var(--spacing-xl);
}
.services-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
}
.blog-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
}
.contact-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-xl);
}
/* --- MEDIA QUERIES --- */
@media (max-width: 768px) {
.image-grid, .services-grid, .blog-grid, .contact-grid {
grid-template-columns: 1fr;
}
}
@media (min-width: 768px) {
/* Stili za večje tablice */
.image-grid { grid-template-columns: 1fr 1fr; }
.services-grid { grid-template-columns: repeat(2, 1fr); }
.blog-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 992px) {
/* Stili za namizje */
.about-grid {
grid-template-columns: 1fr 2fr;
gap: var(--spacing-xl);
}
.services-grid, .blog-grid {
grid-template-columns: repeat(3, 1fr);
gap: var(--spacing-xl);
}
.contact-grid {
grid-template-columns: 1fr 1fr;
align-items: flex-start;
}
}"""
"./assets/css/layout/_structure.css" :
"""
/* /assets/css/layout/_structure.css */
/* === OSNOVNA STRUKTURA PODSTRANI === */
.page-main-content {
padding-top: var(--spacing-xl);
padding-bottom: var(--spacing-xl);
min-height: calc(100vh - 80px - 150px);
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 0 var(--spacing-l);
}
.page-title {
font-size: clamp(2.5rem, 6vw, 4rem);
text-align: center;
margin-bottom: var(--spacing-xl);
color: var(--color-primary-accent);
}
.section-title {
font-size: clamp(1.5rem, 4vw, 2rem);
margin-top: var(--spacing-l);
margin-bottom: var(--spacing-m);
color: var(--color-text);
border-left: 4px solid var(--color-primary-accent);
padding-left: var(--spacing-m);
}
.intro-text {
font-size: 1.25rem;
font-style: italic;
font-weight: 500;
line-height: 1.6;
margin-bottom: var(--spacing-l);
color: #555;
}
.page-subtitle {
font-size: clamp(1.1rem, 3vw, 1.4rem);
text-align: center;
max-width: 800px;
margin: 0 auto var(--spacing-xl) auto;
color: #555;
}
.text-section {
margin-bottom: var(--spacing-l);
}
/* === SPLOŠNI STRUKTURNI ELEMENTI === */
.about-image {
width: 100%;
max-width: 400px;
margin: 0 auto;
position: static; /* Privzeta pozicija za mobilne naprave */
}
.about-image img {
width: 100%;
height: auto;
border-radius: 10px;
box-shadow: var(--shadow-medium);
}
/* === SPREMEMBE TUKAJ === */
.grid-image {
width: 100%;
aspect-ratio: 1 / 1; /* SPREMEMBA: Zagotovi kvadratno razmerje */
background-size: cover;
background-position: center;
border-radius: 10px;
box-shadow: var(--shadow-medium);
transition: transform var(--transition-medium), box-shadow var(--transition-medium);
}
.grid-image:hover {
transform: scale(1.03);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
}
.highlight-quote {
margin: var(--spacing-l) auto;
padding: var(--spacing-l);
border-left: 5px solid var(--color-primary-accent);
background-color: rgba(8, 4, 252, 0.05); /* SPREMEMBA: Ujemanje z novo barvo */
border-radius: 0 8px 8px 0;
}
.highlight-quote p {
font-size: 1.1rem;
font-style: italic;
font-weight: 500;
margin-bottom: var(--spacing-m);
}
.highlight-quote cite {
display: block;
text-align: right;
font-style: normal;
font-weight: 600;
}
.concluding-statement {
text-align: center;
padding: var(--spacing-l);
margin: var(--spacing-xl) 0;
border: 1px solid var(--color-border);
border-radius: 8px;
background-color: var(--color-white);
box-shadow: var(--shadow-light);
}
.concluding-statement p {
margin-bottom: 0;
font-size: 1.1rem;
line-height: 1.8;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.content-cta {
text-align: center;
margin-top: var(--spacing-xl);
}
.page-hero {
padding: var(--spacing-l) 0;
text-align: center;
background-color: rgba(8, 4, 252, 0.05); /* SPREMEMBA: Ujemanje z novo barvo */
margin-bottom: var(--spacing-xl);
}
.page-hero .page-title {
margin-bottom: var(--spacing-m);
}
.page-hero .page-subtitle {
font-size: 1.1rem;
max-width: 700px;
margin: 0 auto;
color: #555;
font-style: normal;
}
/* --- KONTAKT IN ZEMLJEVID --- */
.contact-details {
background-color: rgba(221, 226, 229, 0.2);
padding: var(--spacing-l);
border-radius: 8px;
}
.contact-info-item { margin-bottom: 1.5rem; }
.contact-info-item .info-label { display: block; font-size: 0.9rem; font-weight: 600; color: #777; margin-bottom: var(--spacing-xs); }
.contact-info-item .info-data { font-size: 1.1rem; margin: 0; }
.contact-info-item .info-data a { word-break: break-all; }
.map-placeholder { width: 100%; height: 300px; border-radius: 8px; overflow: hidden; margin-top: var(--spacing-l); background-color: #e9e9e9; box-shadow: inset 0 2px 4px rgba(0,0,0,0.06); }
.map-placeholder iframe { width: 100%; height: 100%; border: 0; }
/* --- UTILNOSTI --- */
.animate-on-scroll {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
}
.animate-on-scroll.is-visible {
opacity: 1;
transform: translateY(0);
}
/* --- MEDIA QUERIES --- */
@media (max-width: 768px) {
/* SPREMEMBA: Odstranjen min-height */
}
@media (min-width: 768px) {
/* SPREMEMBA: Odstranjen min-height */
}
@media (min-width: 992px) {
.about-image {
max-width: 100%;
position: sticky; /* Omogoči lepljivo pozicijo */
top: calc(var(--spacing-l) + 80px); /* Odmik od vrha + višina glave */
align-self: start; /* Zagotovi pravilno poravnavo znotraj grid celice */
}
}"""
"./assets/css/main.css" :
"""
/* /assets/css/main.css */
/* Ta datoteka služi kot glavna vstopna točka in uvaža vse ostale CSS parciale. */
/* 1. Base Styles - Osnovni stili, spremenljivke in tipografija */
@import url('base/_variables.css');
@import url('base/_reset.css');
@import url('base/_typography.css');
/* 2. Layout Styles - Strukturni elementi in mreže */
@import url('layout/_structure.css');
@import url('layout/_grids.css');
/* 3. Components - Ponovno uporabljivi gradniki (gumbi, kartice, itd.) */
@import url('components/_header.css');
@import url('components/_footer.css');
@import url('components/_slider.css');
@import url('components/_buttons.css');
@import url('components/_cards.css');
@import url('components/_accordion.css');
@import url('components/_contact-form.css');
/* 4. Page-Specific Styles - Stili za specifične tipe strani */
@import url('pages/_article.css');
@import url('pages/_storitve.css');
@import url('pages/_homepage.css');
@import url('pages/_cenik.css'); /* SPREMEMBA: Uvoz nove datoteke za cenik */"""
"./assets/css/pages/_article.css" :
"""
/* /assets/css/pages/_article.css */
/* === STILI ZA PODSTRANI POSAMEZNIH STORITEV === */
.service-hero {
padding: var(--spacing-xl) 0;
text-align: center;
background-color: #f7f9fa;
border-bottom: 1px solid var(--color-border);
}
.service-hero .page-title {
color: var(--color-primary-accent); /* SPREMEMBA: Naslov je sedaj v novi primarni barvi */
}
.service-content-wrapper {
max-width: 800px;
margin: var(--spacing-xl) auto 0 auto;
}
.service-content-wrapper .section-title {
margin-top: var(--spacing-xl);
}
.service-content-wrapper p {
font-size: 1.05rem;
line-height: 1.8;
}
.service-content-wrapper strong {
color: var(--color-primary-accent-dark);
}
.service-tagline {
font-size: 1.1rem;
font-weight: 600;
text-align: center;
text-transform: uppercase;
letter-spacing: 1px;
margin: var(--spacing-xl) 0;
color: var(--color-primary-accent);
}
/* === STILI ZA STRAN POSAMEZNEGA ČLANKA (BLOG) === */
.article-header {
text-align: center;
margin-bottom: var(--spacing-xl);
}
.article-header .page-title {
margin-bottom: var(--spacing-m);
}
.article-meta {
font-size: 0.9rem;
color: #777;
margin-bottom: var(--spacing-l);
}
.article-hero-image {
width: 100%;
height: 250px;
background-size: cover;
background-position: center;
border-radius: 10px;
margin-bottom: var(--spacing-xl);
box-shadow: var(--shadow-medium);
}
.article-content {
max-width: 750px;
margin: 0 auto;
}
.article-content h2,
.article-content h3 {
margin-top: var(--spacing-l);
margin-bottom: var(--spacing-m);
font-size: 1.5rem;
color: var(--color-primary-accent); /* SPREMEMBA: Tudi ti naslovi so sedaj v novi primarni barvi */
}
.article-content p {
font-size: 1.05rem;
line-height: 1.8;
margin-bottom: 1.5rem;
}
.article-content ul {
list-style-position: inside;
padding-left: 1rem;
margin-bottom: 1.5rem;
}
.article-content li {
margin-bottom: 0.75rem;
}
.article-content blockquote {
margin: var(--spacing-l) 0;
padding-left: var(--spacing-l);
border-left: 4px solid var(--color-primary-accent);
font-style: italic;
font-size: 1.2rem;
color: #555;
}
.article-content strong {
color: var(--color-text);
}
/* --- MEDIA QUERIES --- */
@media (max-width: 768px) {
.article-hero-image {
height: 250px;
}
}
@media (min-width: 768px) {
.article-hero-image {
height: 350px;
}
}
@media (min-width: 992px) {
.article-hero-image {
height: 400px;
}
}"""
"./assets/css/pages/_cenik.css" :
"""
/* /assets/css/pages/_cenik.css */
/* Stili za hero odsek na strani cenika */
.cenik-page-hero {
padding: var(--spacing-xl) 0;
background-color: rgba(8, 4, 252, 0.05);
margin-bottom: var(--spacing-xl);
}
/* SPREMEMBA: Povečana maksimalna širina za več prostora */
.cenik-page-hero .container {
display: flex;
align-items: center;
gap: var(--spacing-xl);
max-width: 1100px;
margin: 0 auto;
}
.cenik-hero-text-content {
flex: 1;
text-align: left;
}
.cenik-page-hero .page-title {
color: var(--color-primary-accent);
font-size: clamp(2.5rem, 5vw, 3.5rem);
text-align: left;
margin-bottom: var(--spacing-m);
}
.cenik-page-hero .page-subtitle {
font-size: 1.1rem;
max-width: 100%;
margin: 0;
color: #555;
font-style: normal;
text-align: left;
}
/* SPREMEMBA: Povečana osnova in maksimalna širina, da je slika večja */
.cenik-hero-image-wrapper {
flex-basis: 55%;
flex-shrink: 0;
max-width: 525px;
}
/* Notranji vsebnik, ki ustvari kvadratno razmerje (1:1) */
.cenik-hero-image-container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 100%;
border-radius: 8px;
overflow: hidden;
box-shadow: var(--shadow-medium);
}
.cenik-hero-image-container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.cenik-page-main-content .special-pricing-note {
background-color: transparent;
border: 2px dashed var(--color-primary-accent);
border-radius: 8px;
box-shadow: none;
max-width: 900px;
margin: var(--spacing-xl) auto 0 auto;
padding: var(--spacing-l);
text-align: center;
}
@media (max-width: 768px) {
.cenik-page-hero .container {
flex-direction: column;
text-align: center;
}
.cenik-hero-text-content {
order: 2;
text-align: center;
}
.cenik-page-hero .page-title,
.cenik-page-hero .page-subtitle {
text-align: center;
}
/* SPREMEMBA: Povečana tudi max širina na mobilnih */
.cenik-hero-image-wrapper {
order: 1;
flex-basis: auto;
width: 100%;
max-width: 400px;
margin: 0 auto var(--spacing-l) auto;
}
}"""
"./assets/css/pages/_homepage.css" :
"""
/* /assets/css/pages/_homepage.css */
/*
Stili za domačo stran, ki omogočajo drsenje in zagotavljajo,
da se vsebina raztegne po celotni višini zaslona.
*/
body.homepage {
display: flex;
flex-direction: column;
min-height: 100vh; /* Zagotovi, da je body vedno vsaj tako visok kot zaslon */
}
.homepage .slider {
flex-grow: 1; /* Omogoči, da se drsnik raztegne in potisne nogo na dno */
display: flex;
align-items: center; /* Vertikalno centrira vsebino drsnika */
width: 100%; /* Zagotovi polno širino */
}"""
"./assets/css/pages/_storitve.css" :
"""
/* /assets/css/pages/_storitve.css */
/* Stili za hero odsek na strani "Predstavitev ponudbe" - usklajeno s cenikom */
.storitve-page-hero {
padding: var(--spacing-xl) 0;
background-color: rgba(8, 4, 252, 0.05);
margin-bottom: var(--spacing-xl);
}
/* SPREMEMBA: Povečana maksimalna širina za več prostora */
.storitve-page-hero .container {
display: flex;
align-items: center;
gap: var(--spacing-xl);
max-width: 1100px;
margin: 0 auto;
}
.storitve-hero-text-content {
flex: 1;
text-align: left;
}
.storitve-page-hero .page-title {
color: var(--color-primary-accent);
font-size: clamp(2.5rem, 5vw, 3.5rem);
text-align: left;
margin-bottom: var(--spacing-m);
}
.storitve-page-hero .page-subtitle {
font-size: 1rem;
line-height: 1.6;
max-width: 100%;
margin: 0;
color: #555;
font-style: normal;
text-align: justify;
}
/* SPREMEMBA: Povečana osnova in maksimalna širina, da je slika večja */
.storitve-hero-image-wrapper {
flex-basis: 55%;
flex-shrink: 0;
max-width: 525px;
}
/* Notranji vsebnik, ki ustvari kvadratno razmerje (1:1) */
.storitve-hero-image-container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 100%; /* Kvadratno razmerje */
border-radius: 8px;
overflow: hidden;
box-shadow: var(--shadow-medium);
}
.storitve-hero-image-container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover; /* Slika ohrani razmerje in zapolni prostor */
display: block;
}
/* Responsive prilagoditve za mobilne naprave */
@media (max-width: 768px) {
.storitve-page-hero .container {
flex-direction: column;
text-align: center;
}
.storitve-hero-text-content {
order: 2;
text-align: center;
}
.storitve-page-hero .page-title,
.storitve-page-hero .page-subtitle {
text-align: center;
}
.storitve-page-hero .page-subtitle {
text-align: justify;
}
.storitve-hero-image-wrapper {
order: 1;
flex-basis: auto;
width: 100%; /* Na mobilnih napravah slika zavzame več širine */
max-width: 400px; /* Povečana tudi max širina na mobilnih */
margin: 0 auto var(--spacing-l) auto;
}
}"""
"./assets/js/main.js" :
"""
document.addEventListener('DOMContentLoaded', () => {
/**
* Funkcija za nalaganje HTML komponent (glava, noga).
* Ta funkcija je bila v originalni kodi, a se na koncu ne uporablja,
* ker so glave in noge vgrajene neposredno v HTML datoteke. Pustimo jo za morebitno kasnejšo rabo.
*/
const loadComponent = (componentPath, placeholderId) => {
return fetch(componentPath)
.then(response => {
if (!response.ok) {
throw new Error(`Napaka pri nalaganju komponente: ${componentPath}`);
}
return response.text();
})
.then(data => {
const placeholder = document.getElementById(placeholderId);
if (placeholder) {
placeholder.innerHTML = data;
}
})
.catch(error => console.error(error));
};
/**
* Funkcija za nastavitev trenutnega leta v nogi.
*/
const setCurrentYear = () => {
const yearSpan = document.getElementById('current-year');
if (yearSpan) {
yearSpan.textContent = new Date().getFullYear();
}
};
/**
* Funkcija, ki nastavi `.active` razred na trenutno aktivno povezavo v navigaciji.
*/
const setActiveNavLink = () => {
const navLinks = document.querySelectorAll('.main-nav a');
const currentPagePath = window.location.pathname;
navLinks.forEach(link => {
// Normaliziramo poti, da se izognemo težavam z zadnjimi poševnicami
const linkPath = new URL(link.href).pathname.replace(/\/$/, "");
const currentPath = currentPagePath.replace(/\/$/, "");
// Korenska stran (/) se mora ujemati samo z linkom, ki kaže na "/"
if (linkPath === "" && currentPath === "") {
link.classList.add('active');
} else if (linkPath !== "" && currentPath.startsWith(linkPath)) {
link.classList.add('active');
}
});
};
/**
* Glavna funkcija za inicializacijo vseh interaktivnih elementov spletne strani.
*/
const initializeApp = () => {
// =================================================================
// === LOGIKA ZA DRSNIK NA DOMAČI STRANI (NESPREMENJENO) ===
// =================================================================
const sliderElement = document.getElementById("slider");
if (sliderElement) {
const slides = sliderElement.querySelectorAll(".slide");
const prevBtn = document.getElementById("prevBtn");
const nextBtn = document.getElementById("nextBtn");
let current = 0;
const total = slides.length;
let slideInterval;
const autoPlayDelay = 5000; // 5 sekund
const showSlide = (index) => {
if (slides.length === 0) return;
slides[current].classList.remove("active");
current = (index + total) % total;
slides[current].classList.add("active");
};
const nextSlide = () => showSlide(current + 1);
const prevSlide = () => showSlide(current - 1);
const pauseSlider = () => clearInterval(slideInterval);
const startSlider = () => {
pauseSlider();
if (slides.length > 1) {
slideInterval = setInterval(nextSlide, autoPlayDelay);
}
};
if (prevBtn && nextBtn) {
prevBtn.addEventListener("click", () => {
prevSlide();
startSlider();
});
nextBtn.addEventListener("click", () => {
nextSlide();
startSlider();
});
}
sliderElement.addEventListener('mouseenter', pauseSlider);
sliderElement.addEventListener('mouseleave', startSlider);
sliderElement.addEventListener('touchstart', pauseSlider, { passive: true });
startSlider();
}
// =================================================================
// === KODA ZA MOBILNI MENI (NESPREMENJENO) ===
// =================================================================
const mobileNavToggle = document.querySelector('.mobile-nav-toggle');
const mainNav = document.querySelector('.main-nav');
if (mobileNavToggle && mainNav) {
mobileNavToggle.addEventListener('click', () => {
const isExpanded = mobileNavToggle.getAttribute('aria-expanded') === 'true';
mobileNavToggle.setAttribute('aria-expanded', !isExpanded);
mobileNavToggle.classList.toggle('open');
mainNav.classList.toggle('open');
});
const navLinks = mainNav.querySelectorAll('a');
navLinks.forEach(link => {
link.addEventListener('click', () => {
if (mainNav.classList.contains('open')) {
mainNav.classList.remove('open');
mobileNavToggle.classList.remove('open');
mobileNavToggle.setAttribute('aria-expanded', 'false');
}
});
});
}
// =================================================================
// === OSTALA OBSTOJEČA KODA (NESPREMENJENO) ===
// =================================================================
// Animacije ob pomikanju (Intersection Observer)
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.animate-on-scroll').forEach(el => observer.observe(el));
// Accordion (Cenik)
document.querySelectorAll('.accordion-item').forEach(item => {
const header = item.querySelector('.accordion-header');
const content = item.querySelector('.accordion-content');
if(header && content) {
header.addEventListener('click', () => {
const isActive = item.classList.toggle('active');
content.style.maxHeight = isActive ? content.scrollHeight + 'px' : null;
});
if (item.classList.contains('active')) {
content.style.maxHeight = content.scrollHeight + 'px';
}
}
});
// =================================================================
// === KODA ZA KONTAKTNI OBRAZEC (NADGRAJENO IN SPREMENJENO) ===
// =================================================================
const contactForm = document.getElementById('contact-form');
if (contactForm) {
// Poiščemo element za sporočila. Če ne obstaja, ga ustvarimo in dodamo.
let formMessageElement = contactForm.querySelector('.form-message');
if (!formMessageElement) {
formMessageElement = document.createElement('div');
formMessageElement.className = 'form-message';
formMessageElement.setAttribute('aria-live', 'polite');
// Vstavimo ga pred gumbom za pošiljanje
const submitButton = contactForm.querySelector('button[type="submit"]');
if (submitButton) {
submitButton.parentElement.insertAdjacentElement('beforebegin', formMessageElement);
} else {
contactForm.appendChild(formMessageElement);
}
}
contactForm.addEventListener('submit', function(e) {
e.preventDefault(); // Preprečimo privzeto pošiljanje obrazca
const submitButton = contactForm.querySelector('button[type="submit"]');
const originalButtonText = submitButton.textContent;
// Zberemo podatke iz obrazca
const formData = {
name: document.getElementById('name').value,
email: document.getElementById('email').value,
message: document.getElementById('message').value
};
// Osnovna validacija na strani klienta (dopolnitev strežniške)
if (formData.name.trim() === '' || formData.email.trim() === '' || formData.message.trim() === '') {
formMessageElement.textContent = 'Prosimo, izpolnite vsa polja.';
formMessageElement.className = 'form-message error visible';
return;
}
// Vizualna povratna informacija, da se je pošiljanje začelo
submitButton.disabled = true;
submitButton.textContent = 'Pošiljam...';
formMessageElement.className = 'form-message'; // Skrijemo prejšnja sporočila
// Pošljemo podatke na PHP skripto z uporabo Fetch API
fetch('/api/send_mail.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
})
.then(response => response.json())
.then(data => {
// Ko prejmemo odgovor od strežnika, ga prikažemo
formMessageElement.textContent = data.message;
if (data.success) {
formMessageElement.classList.add('success', 'visible');
contactForm.reset(); // Počistimo obrazec ob uspehu
// Resetiramo števec znakov
const charCounter = document.getElementById('char-counter');
if(charCounter) {
const maxLength = document.getElementById('message').getAttribute('maxlength');
charCounter.textContent = `${maxLength} znakov na voljo`;
charCounter.className = 'char-counter';
}
} else {
formMessageElement.classList.add('error', 'visible');
}
})
.catch((error) => {
// V primeru mrežne napake ali če strežnik ni dosegljiv
console.error('Napaka pri pošiljanju:', error);
formMessageElement.textContent = 'Prišlo je do napake pri povezavi. Prosimo, poskusite kasneje.';
formMessageElement.className = 'form-message error visible';
})
.finally(() => {
// Ne glede na rezultat, gumbu povrnemo prvotno stanje
submitButton.disabled = false;
submitButton.textContent = originalButtonText;
});
});
// Logika za števec znakov (ohranjeno in nespremenjeno)
const messageTextarea = document.getElementById('message');
const charCounter = document.getElementById('char-counter');
if (messageTextarea && charCounter) {
const maxLength = messageTextarea.getAttribute('maxlength');
messageTextarea.addEventListener('input', () => {
const currentLength = messageTextarea.value.length;
const remaining = maxLength - currentLength;
charCounter.textContent = `${remaining} znakov na voljo`;
charCounter.classList.remove('warning', 'limit');
if (remaining < 0) {
charCounter.classList.add('limit');
} else if (remaining <= 20) {
charCounter.classList.add('warning');
}
});
}
}
// =================================================================
// === GUMB ZA NA VRH (NESPREMENJENO) ===
// =================================================================
const backToTopButton = document.getElementById('back-to-top-btn');
if (backToTopButton) {
window.addEventListener('scroll', () => {
if (window.scrollY > 300) {
backToTopButton.classList.add('visible');
} else {
backToTopButton.classList.remove('visible');
}
});
backToTopButton.addEventListener('click', (e) => {
e.preventDefault();
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
}
};
// --- Glavni Zagon Aplikacije ---
// Poenostavljen zagon, saj nalaganje komponent ni potrebno.
setCurrentYear();
setActiveNavLink();
initializeApp();
});"""
"./blog/bodite-odgovorni-sami-do-sebe/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bodite odgovorni tudi sami do sebe | Blog</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="container">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<div class="article-hero-image animate-on-scroll" style="background-image: url('https://placehold.co/1200x500/9B5E63/FFFFFF?text=Odgovornost');"></div>
<article class="article-content">
<p class="animate-on-scroll">Bolezni in osebne krize so pogosto rezultat tega, da smo pozabili prisluhniti subtilnim ritmom naše duševnosti. Ne samo pretirano delo; tudi pretiravanja z užitki in tovrstno trošenja samega sebe so lahko vzroki izčrpanosti. Zato je smiselno, da si, kadar smo ogroženi ali zbolimo, postavimo za cilj zmanjšanje stresa.</p>
<h3 class="animate-on-scroll">Poslovni stres pot do zanikanja</h3>
<p class="animate-on-scroll">Morebiti trenutno dobro funkcionirate pod pritiskom in se ne zavedate, da vas poslovni stres dela vse bolj grobega, in da je samo vprašanje časa, kdaj bo vaša energičnost prešla v nevarnost nekontroliranega izliva energije. To kar vi zase imenujete energičnost, jaz kot integralni psihoterapevt razumem kot naelektreno eksplozivno borbenost in agresivnost, četudi bo vaš logični um to zanikal. Če ne znate, ne želite ali ne zmorete komunicirati s seboj od znotraj, se boste znašli pred lastnim zidom. Če se ne zavedate, kaj počnete s takšnim odzivanjem samemu sebi, brez dvoma s tem povzročate ranjenost drugih ljudi, in to najprej v čustvenem smislu. Bolezni in osebne krize so pogosto rezultat tega, da smo pozabili prisluhniti subtilnim ritmom naše duševnosti. Ne samo pretirano delo; tudi pretiravanja z užitki in tovrstno trošenja samega sebe so lahko vzroki izčrpanosti. Zato je smiselno, da si, kadar smo ogroženi ali zbolimo, postavimo za cilj zmanjšanje stresa.</p>
<h3 class="animate-on-scroll">Bolezenska obolenja vodstvenih kadrov</h3>
<p class="animate-on-scroll">Bistvo premagovanja stresa je začasna in občasna izključitev samega sebe iz aktivnosti v zunanjem svetu, saj sta prenaprezanje in prevelika izpostavljenost stresu pripomogla k temu, da smo zboleli. Če več let zanemarjate opozorilna znamenja in namesto počitka in sprostitve, nadaljujete s svojim stilom življenja, hkrati pa odstranjujete bolezenske znake s stimulansi (kava, čaj, pijača, zdravila) namesto da bi se dotaknili vzroka za izčrpano energijo, vam lahko telo vrne z mnogo močnejšim znakom, kot je smrkanje ali kašelj.</p>
<h3 class="animate-on-scroll">Reakcija na stres je individualna</h3>
<p class="animate-on-scroll">Reakcijo na stres, ki je vedno individualna, določa interakcija med mnogimi dejavniki: med osebnostjo, stresorji v delovnem okolju, stresorji v osebnem življenju in med podporo znotraj in zunaj delovnega okolja. Prispevajo tudi individualni strahovi človeka, ki je v dalj časa trajajočem stresu, kot so občutki strahu pred vsakdanjostjo življenja, enoličnostjo in notranjo praznino, pred navidezno nerešljivim problemom, pred neprijetnim sodelavcem ali življenjskim partnerjem; ter strahove, vezane na vsakdanje navade, ki jih ljudje občutijo kot škodljive, a jih ne zmorejo preseči, razen s prisilnim vedenjskim odpovedovanjem.</p>
</article>
<div class="content-cta animate-on-scroll">
<a href="/blog/" class="back-to-blog">← Nazaj na vse članke</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./blog/harmonicni-razplet/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Harmonični razplet | Blog</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="container">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<div class="article-hero-image animate-on-scroll" style="background-image: url('https://placehold.co/1200x500/A4B494/FFFFFF?text=Ravnovesje');"></div>
<article class="article-content">
<p class="animate-on-scroll">Pomembno je doumeti, da psihoterapija deluje s fizično energijsko, psihološko in duhovno komponento. V nas spodbuja pristno praktično spoznavanje samega sebe in delov naše osebnosti, kot so fizično telo, duša, duh in zavest, ki so postali skozi naš tok dogodkov - dogajanj v življenju - atrofirane ali neuporabljene.</p>
<p class="animate-on-scroll">Razumite, da se ni mogoče osvoboditi svojih neugodnih občutkov, stisk, nezadovoljstva, strahu, "jeze", ki jo imamo na drugega človeka, ali na družino, na našo okolico in do sveta, ter občutkov krivde in razmišljanj o morebitnih bodočih neugodnih življenjskih scenarijih, saj nam ni razumljivo oziroma nam je nejasno - prikrito, zakaj se nam to sploh dogaja, in zakaj se počutimo tako čustveno psihično, velikokrat pa tudi telesno fizično energetsko zelo neugodno, absolutno pa brez radosti v duši.</p>
<p class="animate-on-scroll">Doumeti je važno, da ne gre za karmo, kot je sedaj moderno reči, temveč naša zavest deluje tako, da nas želi zaščititi, zato v operativnem spominu ne moremo zadržati vseh informacij. nekatere negativne izkušnje, spomini, čustva in razmišljanja gredo v neko plast v človeku, kjer se nabirajo, nabirajo, nabirajo... Na našo žalost pa se tam ne morejo kar same predelati, preoblikovati, osvobajati, saj ostanejo v "oklepu - v kletki" zavesti.</p>
<p class="animate-on-scroll">Mi namreč lahko te naše neugodne izkušnje, razmišljanja in čustva prepoznavamo, jih preoblikujemo, se jih osvobajamo le - z zavestjo, z našim iskrenim namenom, da to želimo aktivno razreševati, kar psihoterapevtsko delo na sebi z ozaveščenim psihoterapevtom tudi predstavlja.</p>
<p class="animate-on-scroll">Harmonični razplet katere koli življenjske situacije, za poiskanje več empatije do samega sebe in do vsega okoli sebe, za najdenje pristne ljubezni in življenjske radosti v samem sebi in tudi do sveta, pa je odvisno od naše motivacije in od naše volje in hrabrosti, da rešimo svoje težave, ki jih jaz imenujem - naloge, ki nam jih postavlja življenje. Problemi so torej naloge - naloge pa je važno raz-reševati - rešiti.</p>
<h3 class="animate-on-scroll">Spoznavanje samega sebe skozi psihoterapijo z ozaveščenim psihoterapevtom!</h3>
<p class="animate-on-scroll">- pomeni subtilno delo na samem sebi in na svojih notranjih potencialih, in takšna psihoterapija ima pomembno vlogo v življenju modernega človeka, ki prepoznava izjemno pomembnost notranjega ravnotežja, miru in povezanosti s samim seboj ter z najdenjem svoje lastne moči in življenjske radosti.</p>
</article>
<div class="content-cta animate-on-scroll">
<a href="/blog/" class="back-to-blog">← Nazaj na vse članke</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./blog/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Blog | Mag. Hermina Merc</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<!-- CSS Stylesheet -->
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="page-hero">
<div class="container">
<h1 class="page-title">Blog</h1>
<!-- === POPRAVEK: Zamenjan podnaslov === -->
<p class="page-subtitle">Moji avtorski strokovni članki, spoznanja, poglobljena razmišljanja o psihoterapiji delo na sebi, in o človekovem osebnostnem razvoju, ter o Poteh večnega razvoja celovitega zdravja telesa in duše. Naj vam dajo navdih in radost na Poti življenja.</p>
</div>
</section>
<section class="container">
<!-- === POPRAVEK: Dodani uvodni sliki === -->
<div class="image-grid">
<div class="grid-image" style="background-image: url('/assets/images/home-slider-07-papiga.webp');"></div>
<div class="grid-image" style="background-image: url('/assets/images/blog-sadje-ogledalo.webp');"></div>
</div>
<!-- === POPRAVEK: Celotna vsebina bloga v eni datoteki === -->
<article class="article-content" style="max-width: 800px;">
<p>Verjetno se strinjate, da življenje vsakogar testira, a četudi boste nerazumljeni, bodite neustavljivi, in nikoli ne odnehajte. bodite hrabri. Psihoterapija pomeni poglobljeno psihološko delo na sebi in spoznavanje sebe skozi celostno usmerjeno psihoterapijo, in to pomeni, da začnete živeti tako, da druge inspirirate, ne pa impresionirate.</p>
<p>Že Bruce Lee je govoril, da če želimo biti srečni in uspešni, je pravilo št. 1: najprej spoznaj samega sebe, preden spoznaš svet. In bodi hraber. kajti če ne spoznaš samega sebe, te bo kdo drugi z lahkoto naredil takšnega kot on hoče, da ti si. A sprejeti je potrebno lastno odgovornost, ne pa ostajati pasiven, lenoben, ali ostajati v »coni komforta«. imej hrabrost, da se začutiš, da se spoznaš in stopaš na pot sprememb. Ko se spoznavaš, se začneš spreminjati od znotraj, spreminjaš pa tudi svoje vedenje, saj si dojel nekatere impulse, ki ti ne služijo več. in tako dejansko ozaveščaš svoje življenje in pristne danosti avtentične darove, ki so v tebi, a tega ne živiš.</p>
<p>V psihoterapiji z ozaveščenim psihoterapevtom skozi delo na sebi in opazovanje samega sebe in svoje osebnosti, imaš možnost spoznavanja samega sebe. In v tem tvojem procesu prebujanja, spoznavanja samega sebe in zato svojega nenehnega razvijanja od znotraj navzven, ti je ozaveščen psihoterapevt lahko v resnično empatično podporo in pomoč. Daj, opogumi se in naredi prvi korak k odločitvi za psihoterapijo - da se premakneš z mesta, kjer si zdaj. Nato naredi naslednji korak. in potem še naslednjega, in stopaj naprej…vedno naprej! na poti tvojega življenja.</p>
<h3 class="section-title">Psihoterapija z ozaveščenim psihoterapevtom</h3>
<p>- nenehno poteka v smeri človekovega neskončnega razvoja.</p>
<p>Ljudje smo kompleksni, hkrati živimo in funkcioniramo na mnogih nivojih. zato se v psihoterapiji človeka tako tudi obravnava. Vloga ozaveščenega psihoterapevta je podpreti klienta, da je pripravljen z večjim zaupanjem kot do sedaj spoznati sebe in ugotoviti, na katerem nivoju je vzrok za njegovo stanje neravnotežja v življenju, pa naj gre za določeno energijsko blokado, duševne stiske, boleča čustva, boleče spomine, napornih stresnih situacij, občutke ogroženosti zaradi neugodnega zdravstvenega počutja in/ ali nerešenih travm oddaljene ali nedavne preteklosti, kar vse pogosto direktno vibrira na sedanje podaljšano zdravstveno in duševno stisko človeka.</p>
<p>In če delujete v psihoterapevtskem procesu dela na sebi z večjim zavedanjem iz srca, in z zaupanjem ter s hrabrostjo odpirati, prevetriti poti, po katerih potujete, vam vaša duša, pravzaprav pa kar vaša celovita osebnost nenehno odstirata »sence« na vaših življenjskih poteh, kar vas seveda pripelje v notranjo transformacijo, in v razreševanje k rešitvi vaših konkretnih težav, stisk, problemov, nalog, ciljev.</p>
<p>Kot ozaveščen psihoterapevt vam želim tudi povedati, da smo vsi nenehno v procesu učenja in razvoja, ki ga jaz imenujem - naš večni razvoj.</p>
<p>In vedite: jaz vas ne učim ničesar! Samo pomagam vam, da izrazite sami sebe! Da boste resnično sijali navzven, zasijte od znotraj…</p>
<h3 class="section-title">Psihoterapija z ozaveščenim psihoterapevtom</h3>
<p>Pomembno je doumeti, da psihoterapija deluje s fizično energijsko, psihološko in duhovno komponento. V nas spodbuja pristno praktično spoznavanje samega sebe in delov naše osebnosti, kot so fizično telo, duša, duh in zavest, ki so postali skozi naš tok dogodkov - dogajanj v življenju - atrofirane ali neuporabljene.</p>
<p>Razumite, da se ni mogoče osvoboditi svojih neugodnih občutkov, stisk, nezadovoljstva, strahu, "jeze", ki jo imamo na drugega človeka, ali na družino, na našo okolico in do sveta, ter občutkov krivde in razmišljanj o morebitnih bodočih neugodnih življenjskih scenarijih, saj nam ni razumljivo oziroma nam je nejasno - prikrito, zakaj se nam to sploh dogaja, in zakaj se počutimo tako čustveno psihično, velikokrat pa tudi telesno fizično energetsko zelo neugodno, absolutno pa brez radosti v duši.</p>
<p>Doumeti je važno, da ne gre za karmo, kot je sedaj moderno reči, temveč naša zavest deluje tako, da nas želi zaščititi, zato v operativnem spominu ne moremo zadržati vseh informacij. nekatere negativne izkušnje, spomini, čustva in razmišljanja gredo v neko plast v človeku, kjer se nabirajo, nabirajo, nabirajo... Na našo žalost pa se tam ne morejo kar same predelati, preoblikovati, osvobajati , saj ostanejo v "oklepu - v kletki" zavesti.</p>
<p>Mi namreč lahko te naše neugodne izkušnje, razmišljanja in čustva prepoznavamo, jih preoblikujemo, se jih osvobajamo le - z zavestjo, z našim iskrenim namenom, da to želimo aktivno razreševati, kar psihoterapevtsko delo na sebi z ozaveščenim psihoterapevtom tudi predstavlja.</p>
<p>Harmonični razplet katere koli življenjske situacije, za poiskanje več empatije do samega sebe in do vsega okoli sebe, za najdenje pristne ljubezni in življenjske radosti v samem sebi in tudi do sveta , pa je odvisno od naše motivacije in od naše volje in hrabrosti, da rešimo svoje težave, ki jih jaz imenujem - naloge, ki nam jih postavlja življenje. Problemi so torej naloge - naloge pa je važno raz-reševati - rešiti.</p>
<h3 class="section-title">Spoznavanje samega sebe skozi psihoterapijo z ozaveščenim psihoterapevtom!</h3>
<p>- pomeni subtilno delo na samem sebi in na svojih notranjih potencialih, in takšna psihoterapija ima pomembno vlogo v življenju modernega človeka, ki prepoznava izjemno pomembnost notranjega ravnotežja, miru in povezanosti s samim seboj ter z najdenjem svoje lastne moči in življenjske radosti. Odkrivanje notranjega ravnotežja in miru v povezanosti s svojo zunanjo dinamično osebnostjo skozi spoznavanje samega sebe v psihoterapevtskem procesu zelo pozitivno in optimistično vpliva na tretiranje tako rekoč kakršnih koli zdravstvenih težav in neravnovesij.</p>
<p>V psihoterapiji s subtilnim psihološkim ukvarjanjem s samim seboj delujemo v času in prostoru tam, kjer je za nas potrebno, da se sprostimo in osvobajamo - od samega sebe- lastnega ega in ugajanja tujim pričakovanjem, od časa in hitenja, od skrbi, od miselne in fizične napetosti, od neugodnih čustev, razmišljanj in spominov, skratka od notranjih in zunanjih borb vsakodnevnega življenja. Takšna psihoterapija dobesedno regenerira in pomlajuje naše telo, dušo, duha in zavest, skratka pomaga harmonizirati celotno človekovo osebnost.</p>
<h3 class="section-title">Nedavno sem prebrala misel, v katero zelo zaupam, ker poudarja, »da je prava medicina vse tisto, kar človeku pomaga, da samega sebe pozdravi«.</h3>
<p>Pa da, vi sami premikate ozdravljujoče procese v samem sebi. vse ozdravljujoče moči so že v vas, in vi jih lahko enostavno aktivirate skozi spoznavanje samega sebe v psihoterapevtskem procesu. Ob pomoči in podpori ozaveščenega psihoterapevta lahko prepoznavate, odkod so signali v vašem telesu, umu, duši in duhu, ki vam mešajo ter rušijo balans v vašem življenju, in vam prepogosto dobesedno ne puste spati. Za resnično ozdravljenje je pomembno, da jih spoznate, prepoznate in se osvobodite - vseh tistih kanalov, skozi katere prihajajo negativne neželjene informacije in doživljanje.</p>
<p>Vse to je tako lahko in enostavno. Samo odprite se v psihoterapevtskem delu na sebi, da spoznate in začutite ljubezen do sebe, samospoštovanje, hrabrost in radost, in prebudite sebe in svojo autentično osebnost, svoje resnične potenciale. In prav zaradi teh dejavnikov in dejstev mi lahko ozdravimo sebe, dogodki v našem življenju se harmonizirajo, ljudjje, predmeti, rastlinski in živalsi svet, ki nas obkroža pa se začno preobražati v ustvarjalno dinamično resničnost in radost našega življenja.</p>
<blockquote class="highlight-quote">
<p>Naj podelim z vami dragoceno misel, ki jo omenja tudi Eckart Tolle, da »je trpljenje neobhodno, dokler ne doumete, da je nepotrebno.«</p>
</blockquote>
<p>Pa da… resnica o našem otroštvu je shranjena v našem telesu, in četudi jo prikrivamo, skrivamo, odrinjamo od sebe, se ne bo spremenila. Ampak naše telo ne sprejema opravičevanj, in tudi ne kompromisov, vsaj na daljši rok ne zmore tega, in nas bo mučilo, dokler se ne bomo pripravljeni soočiti in spoprijeti z resnico o svojem otroštvu, o svojem življenju. Tisti, ki želi spremeniti življenjski tok, ki ga imenujemo usoda, je potrebno, da spremeni sebe in svoj značaj, svojo osebnost. Mi namreč porabljamo ogromno ogromno ogromno svoje energije za borbo z usodo, ko se trudimo spremeniti svoje življenjske dogodke in situacijo na zunanjem planu, pri tem pa v istem času ničesar ne spreminjamo v našem notranjem svetu.</p>
<p>Nekaj časa je sicer mogoče tako manipulirati in varati samega sebe, da lahko izboljšamo svojo usodo, ne da bi spoznali in spremenili v svoji osebnosti in značaju, kar je pomembno spremeniti. Ampak naše telo in duh, pravzaprav kar naša celotna osebnost bo nekega dne izstavila račun. Človek ima neharmonično zdravstveno stanje in bolezenske težave, če v življenju ne pridobi potrebnega znanja, spoznanja, zavedanja in zavesti o samem sebi.</p>
<p>Bolj kot je človek nesiguren, slabše oziroma manj je sposoben, da prenese negotovost; zato ima močno potrebo, da kontrolira svojo prihodnost in da planira vsako svojo potezo. - Čeprav on to sebi običajno želi pojasniti kot posledico svoje odgovornosti. Ena od stvari, ki jih prinese psihoterapevtsko delo na sebi je tudi spoznanje in ustvarjanje psihične zrelosti, zaradi katere postane človek sposoben, da vse bolj realno vidi realnost in da se začuti usposobljenega, da pristno avtentično reagira in da se znajde tudi v nekaterih nepredvidenih - nepričakovanih situacijah, s čimer bo postal manj tesnoben, občutil pa bo psihično in tudi fizično razbremenitev in notranji mir. In seveda tudi radost v življenju.</p>
<p>Vsako zdravstveno neravnotežje, imenovano bolezen je v bistvu temni madež, ki se pojavi zaradi pomanjkanja znanja in zavedanja, prenizke zavesti. Zavest pa je v bistvu celo telo človeka. Torej, če človek zboli in trpi njegovo celovito zdravstveno počutje in stanje, tako na telesnem kot duhovnem nivoju, se to prvenstveno poraja v njegovi zavesti, šele zatem rezonira - odmeva v njegovem fizičnem telesu.</p>
<p>Dragi vsi, vedite da spoznavanje samega sebe v psihoterapiji - je trajni proces ozaveščanja in osvobajanja travm, stisk, tako na zdravstvenem telesnem kot na duhovnem nivoju, ki so vas odcepila od vaše pristne avtentične narave, da ste postali na nek način sužnji lastnih strahov, frustracij, neugodnih misli, spominov, občutkov in čustev, ki se lahko osvobode in transformirajo skozi psihoterapevtsko delo na sebi z ozaveščenim psihoterapevtom. In še nekaj želim povedati: vaša celostna preobrazba se ob tem dogaja enostavno, z lahkoto, je pa izredno močna in učinkovita.</p>
<p>Da boste resnično sijali navzven, Zasijte od znotraj…</p>
<h2 class="section-title" style="margin-top: var(--spacing-xl);">Moji članki objavljeni v medijih:</h2>
<h3 class="section-title">BODITE ODGOVORNI TUDI SAMI DO SEBE</h3>
<p>Bolezni in osebne krize so pogosto rezultat tega, da smo pozabili prisluhniti subtilnim ritmom naše duševnosti. Ne samo pretirano delo; tudi pretiravanja z užitki in tovrstno trošenja samega sebe so lahko vzroki izčrpanosti. Zato je smiselno, da si, kadar smo ogroženi ali zbolimo, postavimo za cilj zmanjšanje stresa.</p>
<p>Ali prepoznavate pri sebi, da se pretirano čustveno odzovete na življenjske izzive in na ljudi okoli sebe? Ali pa, da z nervozno nestrpnostjo izkazujete nemir in impulzivno nasprotujete vsemu ter izražate despotsko inteligenco na začudenje in zgražanje vaših bližnjih? Morda ste že začeli prepoznavati svojo obsedenost z nekaterimi odločitvami, ki jih ne zmorete sprejeti in izvršiti, ker čutite, da vam tudi njihova uresničitev ne bo prinesla osebnega miru in zadovoljstva?</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Poslovni stres pot do zanikanja</h4>
<p>Morebiti trenutno dobro funkcionirate pod pritiskom in se ne zavedate, da vas poslovni stres dela vse bolj grobega, in da je samo vprašanje časa, kdaj bo vaša energičnost prešla v nevarnost nekontroliranega izliva energije. To kar vi zase imenujete energičnost, jaz kot integralni psihoterapevt razumem kot naelektreno eksplozivno borbenost in agresivnost, četudi bo vaš logični um to zanikal. Če ne znate, ne želite ali ne zmorete komunicirati s seboj od znotraj, se boste znašli pred lastnim zidom. Če se ne zavedate, kaj počnete s takšnim odzivanjem samemu sebi, brez dvoma s tem povzročate ranjenost drugih ljudi, in to najprej v čustvenem smislu. Bolezni in osebne krize so pogosto rezultat tega, da smo pozabili prisluhniti subtilnim ritmom naše duševnosti. Ne samo pretirano delo; tudi pretiravanja z užitki in tovrstno trošenja samega sebe so lahko vzroki izčrpanosti. Zato je smiselno, da si, kadar smo ogroženi ali zbolimo, postavimo za cilj zmanjšanje stresa.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Bolezenska obolenja vodstvenih kadrov</h4>
<p>Bistvo premagovanja stresa je začasna in občasna izključitev samega sebe iz aktivnosti v zunanjem svetu, saj sta prenaprezanje in prevelika izpostavljenost stresu pripomogla k temu, da smo zboleli. Če več let zanemarjate opozorilna znamenja in namesto počitka in sprostitve, nadaljujete s svojim stilom življenja, hkrati pa odstranjujete bolezenske znake s stimulansi (kava, čaj, pijača, zdravila) namesto da bi se dotaknili vzroka za izčrpano energijo, vam lahko telo vrne z mnogo močnejšim znakom, kot je smrkanje ali kašelj. Vedeti je treba, da med tipična zdravstvena obolenja sodobnih ljudi na vodstvenih odgovornih položajih, ki bi radi iz neke vrste notranje »prisile«, ki jo čutijo, čim več čim prej čim bolje storili, ne spadajo samo bolečine pri srcu, občutki pečenja in tesnobnosti v prsih in palpitacije, glavoboli, migrene in bolečine v hrbtu in vratu, vzdraženi želodec in občutki napihnjenosti, temveč tudi panični tesnobni napadi ter ponavljajoče se težave kot so kašelj, alergijske reakcije kože in dihal, nedoločene bolečine v čeljustih, preobčutljivo črevesje, pogostejše uriniranje, drget, spolna otopelost, moten spanec, »prisilke« v obliki vsiljivih misli, ki se jih ni mogoče otresti, kronična izčrpanost ter depresivno razpoloženje.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Reakcija na stres je individualna</h4>
<p>Reakcijo na stres, ki je vedno individualna, določa interakcija med mnogimi dejavniki: med osebnostjo, stresorji v delovnem okolju, stresorji v osebnem življenju in med podporo znotraj in zunaj delovnega okolja. Prispevajo tudi individualni strahovi človeka, ki je v dalj časa trajajočem stresu, kot so občutki strahu pred vsakdanjostjo življenja, enoličnostjo in notranjo praznino, pred navidezno nerešljivim problemom, pred neprijetnim sodelavcem ali življenjskim partnerjem; ter strahove, vezane na vsakdanje navade, ki jih ljudje občutijo kot škodljive, a jih ne zmorejo preseči, razen s prisilnim vedenjskim odpovedovanjem.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Ali je čas za spremembe?</h4>
<p>Če ste začutili, da prihaja čas za neko vrsto osebne transformacije namesto dosedanjega prepuščanja iluzijam, da je z vami vse v najlepšem redu in/ali da so za stresne razmere krivi (samo) drugi, potem svetujem, da preprosto morate najti dovolj poguma, volje, inspiracije, odgovornosti in zavestnosti za lastne spremembe skozi ustvarjalni proces v integralni psihoterapiji. To si morate priznati. Vsako prizanašanje z resnico in iskrenostjo v vlogi tolažilnega sprenevedanja predstavlja zgolj socialne igrice lajšanja osebne krize, in s tem omalovaževanje in izogibanje nujnim soočenjem, ki so v krizi izstopila na površje. Prav kriza namreč kaže, da se z lažmi in iluzijami ega ne da preživeti. Ne bojte se torej celovite preobrazbe. Vi mislite, da brez dosedanje »stabilne« slike o sebi ne boste več vedeli, kdo ste. Da ne boste mogli več eksistirati, da vas bo to uničilo. Zato raje živite in »hranite« iluzije, da ste takšni kot ste sedaj - skoraj idealni, in to samo zato, ker pač želite biti idealni, in si prizadevati za nečim, kar s pravo vrednostjo življenja nima nič skupnega.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Nevarnosti kroničnega stanja</h4>
<p>Če je človek tako močno pod stresom, da ni več osrediščen v samem sebi in ga narušeno zdravstveno ravnotežje še dodatno frustrira, se lahko iz tega razvije kronično stanje kadar gre za življenjsko krizo ali težjo bolezen je lahko takšna »notranja razglašenost« za človeka usodna. Če že čutite energijo za spremembe, ne želite pa odgovoriti na njo na način, ki bi bil za vas koristen in potreben, potem dovoljujete, da vaše življenje še naprej ostane takšno, kot je.</p>
<p style="margin-top: var(--spacing-l);"><em>Mag. Hermina Merc</em></p>
<h3 class="section-title">Terapija s plesom v povezanosti z integralno psihoterapijo združuje vrhunsko znanje integralne psihoterapije z dinamičnim plesnim gibanjem in čutnim telesnim izražanjem</h3>
<p>S čutnim terapevtskim gibanjem se lahko zdravimo, to je dejstvo, ki ga poznajo v medicini, psihologiji in tudi v psihoterapiji. Terapija s plesom je plesanje spontanih izvornih ritmov izražanja gibanja telesa, ki se odvija skozi navdihujoči ples, ko čutno, a z živostjo premikamo svoje telo, kjer ne obstajajo predsodki, kritiziranje ega, ocenjevanje, in kjer začutimo telo, dih, srce, um, dušo in duha kot vibriranje celovite energije.</p>
<p>Kot integralni psihoterapevt jo izvajam v povezanosti z integralno psihoterapijo, ki človeku sicer že sama s svojim celostnim strokovnim pristopom samostojno ali pa v kombinaciji s terapevtskim plesnim gibanjem odpira "notranja" vrata do globljega občutenja osvoboditve spontanosti in dinamičnega ravnotežja pri samem sebi in v življenju.</p>
<p>Tako se torej lahko plesno terapevtska praksa izvaja tudi samostojno kot plesno inspiracijsko gibanje izražanje svojega telesa na globljem nivoju doživljanja. Pri tem imate možnost raziskati, soočiti, ozavestiti, predelati, transformirati ter integrirati vse, kar se je dogajalo v vas (bolečega, jeznega, nerazumljenega, bolnega, nervoznega, radostnega, ljubečega, sproščenega) ne le med plesom, pred ali po njem, temveč tudi to, kar vse ste začutili v plesnem izražanju v zvezi s svojo osebno zgodovino in v življenjskih ciklusih - kot prebujanje intuitivnega, pristnega sveta v vas.</p>
<p>Ta plesno gibalna praksa je še posebej namenjena ljudem v sodobnem tempu življenja, ki so zelo stresno obremenjeni, v domačem in/ali delovnem okolju, in ki ne zmorejo upočasniti kaosa okoli sebe ter zaustaviti lastnega pregorevanja energije, in tudi tistim, ki veliko časa preživijo "v glavi" ter v odgovornem razmišljanju in odločanju ter se vse težje znajdejo v vsej tej svoji nervozni energiji. Če je človek tako pod stresom, da ni več osrediščen v samem sebi, in ga telesnost še dodatno frustrira, se lahko iz tega razvije kronično stanje kadar gre za življenjsko krizo ali težjo bolezen, in je lahko takšna "notranja razglašenost" za človeka usodna. Terapija s plesom vam prinaša priložnost, da poiščete v sebi moč preobrazbe in postanete prijatelj svojemu telesu. Naučite ga imeti radi na moder način!</p>
<p>Vaše duševno stanje se namreč zrcali v telesu. V vašem telesu je zapisana vaša celotna osebna zgodovina, od začetka spočetja do danes. Vse te zgodnje življenjske zgodbe in izkušnje se odražajo v vašem telesnem izražanju (na primer; kakšna je vaša telesna drža pred avtoritetami ali do nasprotnega spola; telesna govorica rok, ki govori o nezavednih, izrinjenih čustvih in mislih; kako se s telesom izražate, ko ste jezni, za razliko, kadar želite sebe predstaviti kot pomembne ali celo kot "nekaj več" od ostalih; kako se premikate s telesom, na primer z nogami, kadar ste negotovi). Telo predstavlja mesto, v katerem se spajajo energije. In ker se skozi ples začne telo bolj svobodno premikati, se premaknejo tudi vaša čustva, zablokiranost v vašem doživljanju in razmišljanju. Vse to lahko skozi gibanje v plesanju prepoznavate, osvobajate, "greste skozi" ter "izplešete". Ne glede na to, o katerem čustvu je govora, takšno terapevtsko plesanje olajšuje izražanje in vzpostavljanje ravnotežja ter odpira vašo lastno preobrazbeno moč osvoboditev od jeze; opogumljanje, če ste zaskrbljeni in prestrašeni; potešitev, kadar ste žalostni, potrti. Na nivoju zavesti pa ima oseba občutek sproščenosti, radosti, odprtosti k ustvarjalnemu potencialu, in večji zavestnosti.</p>
<p>S terapevtskim plesanjem se namreč zdravilno povežemo ne zgolj s svojim telesom in dihanjem, temveč tudi s svojim srcem, umom, dušo in duhom. Vsi vemo, da nekaterih stvari v življenju dejansko z empiričnimi znanstvenimi metodami ne moremo pojasniti, ker so izkustvene. Ko boste plesali v ritmu lastnega notranjega utripa svojega bitja, boste resnično oživeli!</p>
<p>Dvignite se na višji nivo zavedanja, kjer boste sposobni ustvarjati in oplemeniti sebe pogumno, s humorjem in samozavestjo. V plesnem gibanju in v kombinaciji z integralno psihoterapijo obstaja mnogo možnosti za razrešitev, in če vam jo kdo preprečuje, ste to vi sami s svojimi iluzijami in strahovi pred snemanjem (svojih) mask in oklepov.</p>
<p>In ne nazadnje, v kolikšni meri se zavedate, da tudi vaša seksualna zgodovina vpliva na vsak del vaše duševnosti? In da se vse, kar muči vašo dušo v zvezi s tem, odraža skozi vaše telo? Mnogo vaših strahov je namreč osnovanih na tem, kaj ste ustvarili sebi in kaj ste storili drugim v svojem seksualnem življenju. Marsikdo tega ne želi videti, ker je preveč boleče in ker to obsoja kot slabo ali pa kot slabost.</p>
<p>Mag. Hermina Merc je klinični psiholog specialist psihoterapevt</p>
<h3 class="section-title">SOOČANJE Z NOTRANJIMI OBČUTKI ali USTVARJALNA MOČ PSIHOTERAPIJE</h3>
<p>Težko je strpati vse svoje želje, razmišljanja, hrepenenja, strahove v tako omejeni prostor kot je telo. Zakaj smo stalno napeti, nemirni in se počutimo prikrajšani, izčrpani, prenatrpani, zablokirani, v zatečenem stanju? Ni nujno, da se vsega tega tudi zavedamo, a zagotovo vsakdo občuti, da nekaj ni v redu. Vsako telo ima v sebi zapisane vse svoje zgodbe in jih pripoveduje na svoj lasten način (v obliki bolečine, izčrpanosti, otopelosti, poškodbe, bolezni).</p>
<p>Potrebno je razumeti, da je delitev na telo in um absolutno napačna. Če ločite sebe od svojega telesa, to vodi v potlačitev. Čim bolj tlačite telo, tem bolj boste razočarani, kajti potlačitev na daljši rok ni mogoča. Možno je doseči trenutno premirje, ampak potem boste spet poraženi.</p>
<p>Psihoterapija je zdravilo, ki zdravi razklanost telesa in duše. Psihoterapevti imamo isti namen dvigniti ljudi k zrelosti in preobrazbi, a poti in tehnike za to so različne.</p>
<p>Ni sramotno, če v življenju poiščemo vodstvo. Samo pameten človek sprevidi, da smo v določenih življenjskih preizkušnjah kakor otroci. Kdor ima namreč premalo izkušenj, ponavadi ne deluje modro.</p>
<p>Do globljega razumevanja sebe in bistva življenja pridemo s samodisciplino in pogumno samoanalizo v psihoterapiji (eksistencialna, telesno-energetska in k duhovnemu samorazvoju orientirana).</p>
<p>Občutiti sebe je prvi korak v psihoterapiji. Zunanji občutek v resnici sploh ni občutek. Je samo moda, kriterij, vsiljen od zunaj. Na primer, vsi imamo ustaljeno podobo o tem, kaj je lepo, s katero se večina ljudi strinja, zato obstaja občutek za lepo in grdo, sicer ne. Pomembno pa je spoznati notranje občutenje sebe, da jasno prepoznamo razlike. In zato se je potrebno soočiti s svojo osebno zgodovino, z notranjimi zemljevidi sebe iz otroštva, mladosti, odraslosti.</p>
<p>Sleherna zasvojenost izvira iz upiranja temu, da bi se soočili s svojo bolečino, strahom, praznino (čustveno in bivanjsko). Vsaka zasvojenost (alkohol, droga, tablete, cigarete, hrana, seks, drugi človek, pretiravanje v iskanju čutnih užitkov, televizija, internet, telefon) pomeni uporabiti nekoga ali nekaj za to, da prikrije našo bolečino, strah, negotovost, praznino!</p>
<p>Na primer problemi s spanjem: Greste spat, vso noč se obračate v postelji, ker se um ne more umiriti in premakniti iz aktivnosti v neaktivnost. Da bi zaspali, vzamete pomirjevalo. Toda prisilen spanec vam ne more dati dovolj počitka; je samo površinski. Spanje postane mora.</p>
<p>Pri vsaki zasvojenosti pride trenutek, ko »omamljanje od zunaj« na vas ne deluje več, in tedaj občutite še več bolečine in tesnobnosti kot kadarkoli prej.</p>
<p>Biokemiki vas bodo kmalu naredili odporne na jezo ali odporne na tesnobo, ker bo vaš telesni kemizem nadzorovan, toda s tem še ne boste zdravi, zadovoljni, uresničeni. Kajti čustva kot je jeza, razdražljivost, tesnobnost so znotraj vas in ne morete jih zmeraj obvladovati. Morajo se pokazati, da jih lahko razumete in preobrazite. Človekova preobrazba pa nima meja.</p>
<p>Kadar mečete energijo iz sebe (na primer storilnostni športi in konjički), se lahko čutite razbremenjene, toda ta razbremenitev je trenutna, saj ste zgolj zamenjali eno obliko dela za drugo (šport), ki pa je še vedno delo(vanje). Čemur ljudje običajno pravijo užitek, je samo izmetavanje konfliktnih energij. Vaša življenjska energija in vitalnost pa uhajata, namesto da bi ju revitalizirali. Sicer morda za nekaj trenutkov čutite sprostitev napetosti, toda to je tako kot bi na obroke metali proč svoje življenje.</p>
<p>Ne bežite več pred seboj s pomočjo družbe, društev, prekomernega vdajanja trenutnim užitkom. Samo zato ker je množica z vami, ste sproščeni. Prilagodili ste se družbi, sebe pa ne občutite več.</p>
<p>Vsi hrepenimo po tem, da bi izpolnili sebe, svoj jaz. Toda če izberemo bližnjico, potem se bomo na koncu izgubili. Najkrajša pot je preko bogastva, moči, politike. Toda to je lažna, zgolj estetska osebnost. Vse življenje bežimo od sebe, od svoje pristne in avtentične narave. Drugi so nam pomembni zato, ker nam pomagajo bežati. Zato smo prepogosto usmerjeni k drugim, namesto da bi iskali sebe od znotraj.</p>
<p>Vsak sodobni človek pa mora spoznati lastno individualnost in sprejeti odgovornost zanjo.</p>
<p>Ne poskušam vas prepričati. Intelektualno prepričanje sploh ni nikakršno prepričanje. Samo sporočam vam dejstvo. Meni kot psihoterapevtu gre le za to, da ustvarim takšno situacijo, v kateri vaš jaz s svojimi pristnimi, najglobljimi občutji stopi iz vas nasproti meni. V psihoterapevtskem procesu si prizadevam ustvariti raznovrstne situacije. In kadar v psihoterapiji postavljate vprašanja, vprašujte vprašanja, ki so osebna, intimna, pristna. Morate se zavedati, kaj v resnici sprašujete. Ali je to nekaj, kar vam resnično kaj pomeni? Če bo odgovorjeno, ali se vam bo odprla nova perspektiva? Ali se bo nekaj dodalo vašemu življenju, ali se boste skozenj na kakršnikoli način spremenili, preobrazili?</p>
<p>Prav v vsakem poklicu so ciklusi uspeha, ko se vse dobro na videz kar samo od sebe steka k vam, pa cikli neuspeha, ko vam vse uhaja iz rok. Če se v takih časih oklepate starega in upirate sedanjosti, pomeni, da nočete iti vštric z življenjskim tokom, in zaradi tega trpite.</p>
<p>Ni res, da je ciklus uspešnosti dober, ciklus neuspešnosti pa slab, saj nič ne more večno rasti. Če bi rast kar trajala, bi nekega dne postala pošastna in uničevalna. Padajoči ciklus je zato vsekakor pomemben za globlje občutenje in zavedanje samega sebe. Veliko bolezni nastane prav zato, ker se upiramo ciklusom nižjih energij, ki pa so bistvenega pomena za telesno in duševno prenovo.</p>
<p>Med tipično obolenja sodobnega človeka ne spadajo samo bežne bolečine pri srcu, občutki pečenja in tesnobe v prsih ali pridružene palpitacije, glavoboli in bolečine v hrbtu, vzdraženi želodec in občutki napihnjenosti, temveč tudi ponavljajoče se telesne težave kot so kašelj, dihalne in kožne alergije, nedoločene bolečine v čeljustih, preobčutljivo črevesje, pogostejše uriniranje, trepet (drget), spolna otopelost.</p>
<p>Prisila, ki jo čutite, da bi čimveč čimprej storili, in nagnjenje do tega, da črpate občutek lastne vrednosti in identitete iz zunanjih dejavnikov (iz dosežkov, statusa, pomembnih prijateljev, priimka družine) so slepilo. Tako se utegne zgoditi, da se vmeša telo, in si, da bi vas obvarovalo, samo nakoplje bolezen ter vas s tem prisili, da se ustavite in poglobite vase. Opazite lahko, kje ste ujeti v starih načinih delovanja, ki ne ustrezajo več vašim sedanjim potrebam in potencialom.</p>
<p>Psihoterapija neizbežno vodi k spremembam in odpravlja inercijo, ki se kaže kot zastala energija v telesu, obrambni zid okrog čustev in negibna, neprožna stališča v umu. Odpravlja pa tudi mišične zakrčenosti, ki so posledica vašega odzivanja na stresne dogodke.</p>
<p>Sprašujete me, kaj torej storiti? Spoznajte sebe, zavestno in premišljeno. Pojdite v psihoterapijo zavestno. Tipajte v temi in nikar se ne bojte zmot. Sprejetje tega, kar je, še posebej, če gre vse narobe, ni vdanost v usodo ali sprejetje neželenih življenjskih okoliščin. Raje se zavedajte in si priznajte, da bi radi prišli iz tega. Zatorej se bolečini, strahu, praznini ne izmikajte, soočite se z njimi, občutite jih do kraja.</p>
<p>Psihoterapija ni metoda, temveč ustvarjalni proces, to ni psihološka tehnika, temveč razumevanje sebe in namena življenja na globljem nivoju. Ustvarjalna moč psihoterapije namreč počiva v našem večjem zavedanju življenjskega namena in znanja o doseganju tega namena.</p>
<p>Zato ste v psihoterapiji iskalec, ne pa učenec, kajti resnične informacije, ne pa konfekcijske formule, pridejo iz vaših notranjih globin in ne od zunaj. In ko iščete, občutite olajšanje in vznesenost.</p>
<p>Vedite, da velike spremembe zahtevajo svoj čas. Za te se mora vsakdo truditi, mora si jih želeti. Opraviti mora veliko dela, psihoterapevt ne bo naredil vsega. To, da vam kdaj kaj spodleti, ni pomembno. Vsakemu kdaj kaj spodleti. Ne smete pa izgubiti poguma.</p>
<p>Da bi lahko sebe uravnotežili, morate poznati svoje senčne plati. In te morate spoznati popolnoma, tako da ne postanete žrtve samih sebe.</p>
<p>Pri psihoterapevtskem delu torej ne gre samo za duševno ravnotežje, temveč za duhovno razsežnost lastnega bitja. Ker če samo spreminjate to, kar počnete, v resnici ne spreminjate ničesar. Ostajate isti. Spremeniti in preobraziti se morate v sebi, postati bolj zavedajoči, vaše vedenje pa temu procesu naravno sledi.</p>
<p>Imejte torej pogum, da naredite prvi korak. In vedite, da psihoterapevt ve, da se ljudje ne morejo odpreti »čimprej«. Vsakdo ima svoj lasten način. Poskušati morate in psihoterapevt vam bo pomagal.</p>
<p>In dovolite, da vas preseneti to, »kar je pred vami«.</p>
<h3 class="section-title">STRES JE UPIRANJE SPREMEMBAM</h3>
<p>Če postajajo nemir, napetost, utrujenost, brezvoljnost in pomanjkanje radosti stalni spremljevalci našega življenja, je čas, da se zaustavimo in poiščemo globlji stik s seboj. Kljub hitremu, frenetičnemu vrvenju življenja okoli nas, namreč ni treba, da podležemo stresu. »Stres je v osnovi odpor proti spremembam. Ko se stvari spreminjajo, mi pa ne želimo narediti spremembe pri sebi, ki je potrebna, bomo izkušali stres tako dolgo, dokler se bomo upirali spremembi. V življenju pa moramo biti pogumni, ni nam potrebno čakati na prebuditev do starosti. Biti moramo zelo živi in igrivi, kar pomeni tudi tvegati, da bomo morda prepoznali in občutili stvari, dogodke, spomine, ki jih ne želimo, in za katere smo mislili, da jih nikoli ne bomo čutili,« pravi Hermina Merc, magistrica klinična psihologinja specialistka in psihoterapevtka z evropsko diplomo ter supervizorka Evropske akademije za psihosocialno zdravje in razvijanje ustvarjalnosti iz Nemčije (EAG Fritz Perls Institut).</p>
<p>Sodobno življenje , ki ga vodi diktat iskanja užitkov in pretirane dejavnosti ter s tem samoizčrpavanja, terja svoj davek: čedalje več ljudi pestijo psihosomatske bolezni, ki na daljši rok vodijo v izgorelost. Ljudje se s stresom spoprijemajo na različne načine.</p>
<p>Nekateri se zatečejo v šport, drugi tlačijo bolezenske znake s poživili, ki začasno dvignejo razpoloženje ali pa si olajšajo dušo v pogovoru s prijatelji, tretji spremenijo življenjski slog, si vzamejo več časa za sproščanje in preživljanje v naravi ...</p>
<p>»Sodobna družba od ljudi pričakuje, da bodo zmogli hitreje misliti, več delati, se odlikovati v vsem, česar se lotijo. Tudi naša pričakovanja do sebe so vedno večja, tako da postaja vzrok za stres pravzaprav vse, česar se lotimo. Nekateri pravijo, da lažje delajo pod »pritiskom«. Če se naprezamo v okviru svojih zmožnosti, bomo morda uspešni, če pa se naprezamo izven tega okvira, se bomo znašli pod fizičnim in/ali psihičnim pritiskom.</p>
<p>Dokler se z rahlim povečanjem pritiska dviga tudi raven adrenalina, se lahko naša učinkovitost res izboljša. Ko pa adrenalin doseže določeno raven, se pritisk neizogibno spremeni v obremenitev, in naša učinkovitost začne strmo padati, kar privede do notranje napetosti, porušenega ravnotežja, dokler končno ne doseže točke zloma. Organizmu namreč zmanjka energije za obnovitev telesnih celic.</p>
<p>Ko ljudje prehodijo pot od utrujenosti do izčrpanosti, so na robu zloma, saj mislijo, da bodo dodatne pritiske zmogli, če se bodo še dodatno potrudili, in namesto da bi učinkovitost rasla, pada,« pravi Hermina Merc, ki pri svoji zasebni klinični psihološki in psihoterapevtski praksi tudi s protistresnimi programi, pomaga ljudem, da si spet povrnejo notranje ravnovesje, mir in vitalnost. Opaža, da večina ljudi prva znamenja bolezenskega procesa zazna kot zmerno nelagodje v splošnem počutju ali v določenih delih telesa, a ga sprejema kot sestavni del življenja ali pa se izgovarjajo na leta.</p>
<p>Duševno preutrujeni ljudje so večinoma ljudje, ki so na begu pred samim seboj. In četudi se morda ne zavedajo, da so v stresu, se ta vselej nekje odraža. Neravnotežja se najprej pojavijo v trebušnem in prsnem delu, šele kasneje se razširijo v celičje. Tako strah in stres občutno prizadeneta kakovost bivanja in krajšata življenjsko dobo. Čeprav se zdi, da stres prihaja vselej od zunaj, so korenine problema v naši notranjosti: v našem zaznavanju, pričakovanjih, prepričanjih in potrebah, je prepričana Hermina Merc.</p>
<p>V svoji praksi srečuje tudi mnogo ljudi, ki doživljajo stres kot izkušnjo živosti, budnosti, občutenje adrenalina. Kadar ne čutijo adrenalinskega vrhunca, postanejo nemirni, razdražljivi, tako rekoč hkrati pa postanejo tudi brezvoljni in malodušni. A s tem ko človek troši svojo življenjsko energijo na vseh ravneh, sčasoma ne čuti več zadovoljstva z naravnim tempom življenja, pravimo, da izgubi občutljivost za svojo pristno naravo. Tak človek ne zna več izpolnjeno živeti današnji dan in se veseliti drobnih dogodkov in stvari. V njem zeva praznina, ki jo nato kompenzira z zunanjimi materialnimi nadomestki: nakupovanje, hrana, odnosi, storilnostna fizična vadba, alkohol, protibolečinske tablete, gledanje televizije, telefoniranje, internet, prekomerno vdajanje najrazličnejšim užitkom. Takšno trošenje svoje energije v človeku sčasoma izzove kronično utrujenost, človek ima občutek, da je izžet, težko je miselno zbran, pešati mu začne tudi spomin, začne mu primanjkovati moči in volje za delovne obveznosti, razlaga psihoterapevtka.</p>
<p>Izgorelost pa ni samo odgovor človeka na obremenitve ali strese zgolj v osebnem življenju, temveč tudi na delovnem mestu. «Za zadovoljstvo pri opravljanju nekega poklica je pomembna usklajenost osebnosti človeka in zahtev delovnega mesta oziroma poklica. Če gradimo poklicno identiteto na doseganju nerealističnih poklicnih ciljev, to zagotovo privede v razočaranje in ustvarjanje neugodne podobe o samem sebi. Poklicni ideal je namreč nekaj, k čemur sicer res težimo, nikoli pa ga v popolnosti ne dosežemo.</p>
<p>Zanimivo je pojmovanje izgorelosti, ki jo nekateri vidijo le kot posledico pretiranega, obremenjujočega dela. Enako pomembno zame kot psihoterapevta je, če ne celo bolj, razumeti izgorelost kot posledico izgube predanosti delu zaradi izgube moralnega smisla lastnega dela.</p>
<p>Človek se odloča za nek poklic, recimo za neko delo iz občutja, da bo lahko deloval in strokovno vplival na svoje delo. Za določeno poklicno področje pa se usmeri ne zgolj v prizadevanju, da bo učinkovit in uspešen, temveč običajno tudi iz občutka, da je sposoben vstopati v medosebne odnose z ljudmi na takšen način, da bo lahko na ljudi vplival. Če pri svojem delu iz različnih vzrokov začutimo, da nam to (več) ne uspeva, se lahko prične proces izgorevanja na fizičnem in/ali psihičnem nivoju. Ker pa človek sebe in svojo delovno učinkovitost prepogosto prepoznava le skozi povratne informacije, teh pa ni ali pa so negativne, sčasoma izgineva njegov občutek o lastni strokovni usposobljenosti in potencialu.«</p>
<p>Ni ene razlage niti ene rešitve in metode za težave. Zagotovo pa je, da prav psihoterapevtsko delo neizbežno vodi k spremembam in odpravlja inercijo, ki se kaže kot zastala energija v telesu, obrambni zid okrog čustev ali neprožna prepričanja v umu. Psihoterapija pa pomaga odpraviti tudi mišične zakrčenosti, ki so posledica posameznikovega odzivanja na življenjske stresne okoliščine in/ali izgorelost.</p>
<p>Druga precej razširjena težava, ki preprečuje izpolnjeno življenje, pa je strah pred novim, neznanim, spremembami. »Mnogo ljudi je težko navdušiti za resnične spremembe. Ne odpirajo se niti sebi, niti svetu, skrivajo se pred neznanim novim drugačnim. Ljudje ostajajo v starih osebnostnih vzorcih in podoživljajo stare travme, ker niso prožni, vseskozi počnejo stvari enako: govorijo, hodijo in občutijo na enak način z omejenim razponom čustev, zato tudi njihova težava ostaja ista. To ni naravno. Vsak trenutek imamo možnost, da si dovolimo izraziti se skozi občutja, ki jih nismo vajeni. Lahko pa odlašamo, češ da je nekaj pretežko ali da ni mogoče. Ljudje pogosto tudi tako mislijo, saj je sodobna družba programirana, da spremembe zahtevajo (pre)več časa in/ali da Nam ne bo uspelo. In zaradi tako nizkega zavedanja samega sebe in svojih razvojnih potencialov takšne ljudi prepogosto spremlja vsiljen nemir in slabo počutje, saj se ne učijo biti soustvarjalci, temveč ostajajo le pasivni opazovalci svojega življenja.«</p>
<p>Sodobni človek bi si duševno ravnotežje najraje kupil po primerni ceni. »A to ni mogoče, saj mora temelj biti lastna izkušnja, osebnostno doživetje in notranji uvid. Osupljivo je, ko se nekega dne zavemo in sprejmemo, česar ne moremo spremeniti, in da smo kot odziv na to sposobni spremeniti sebe.</p>
<p>Do resnične spremembe mora priti znotraj, ne zunaj,« je prepričana psihoterapevtka. Če torej želimo v življenju kaj narediti, če želimo svoje življenje osmisliti, se moramo prebuditi. In psihoterapija nam je lahko pri tem v veliko pomoč. »Psihoterapija pomaga prebuditi sebe, začutiti sebe skozi občutek in globlje zavedanje. Ko zaupamo svojim občutjem, se začnemo spreminjati, preobražati, rasti. V psihoterapevtskem procesu ne razmišljamo o življenju in težavah dualistično: dobro slabo, vredno nevredno, črno belo, temveč v širši perspektivi: dobro in slabo hkrati. Torej je potrebno pogledati za zunanjost nekoga ali nečesa in imeti uvid v globlji pomen nečesa, ne pa soditi ali dajati vrednostnih ocen,« poudarja Hermina Merc, ki pri odkrivanje samega sebe in svojega življenjskega sveta, soočanju z življenjskimi strahovi in iluzijami, subtilno in vedro odpira ljudem vedno nove perspektive, pri čemer kot pomoč svojemu psihoterapevtskemu delu uporablja tudi aktivne metode psihofizičnega in energetskega sproščanja telesa in duha v skupini ali individualno, prav tako pa tudi terapevtski sprostitveni ples ter zvočno terapijo z gongi.</p>
<p>Prvi terapevtski pripomoček pri vseh težavah duševno telesnega področja je, da začnemo zdravljenje pri telesu. »Možnosti je ogromno: hoja, tek, plavanje, terapevtski ples, taoističnain energetska vadba, joga, trening dihanja, progresivno mišično sproščanje, metode globoke relaksacije ipd. Na primer, poglobljena vadba progresivne mišične relaksacije omogoča ciljano usmerjanje pretoka energije v telesu in vseh organskih sistemih, na ta način se sproščajo napetosti, pa naj gre za mišično, čustveno ali psihično zakrčenost. S tako poglobljeno vadbo tudi spodbujamo uravnoteženje in vitaliziranje telesa, uma in duha. Če namreč hočemo v življenju in pri delu uživati, moramo vzdrževati visoko raven energije.«</p>
<p>Hermina Merc klientom , ki so napeti in zakrčeni, pogosto predlaga ob psihoterapiji, tako imenovano bimodalno terapijo, to pomeni kot možnosti za samozdravljenje tudi terapevtski sprostitveni ples, dihalne vaje, energetske vaje, taoistično vadbo, jogo, sofisticirane borilne veščine kot aikido, tai chi, kung fu.</p>
<p>Na ta način opogumlja klienta, da sam v organizirani skupini ali v bimodalni terapiji naredi nekaj zase, tako da začne eksperimentirati in poskušati nove možnosti vedenja, kar skoraj po pravilu pripelje do tega, da so psihoterapevtski cilji hitreje doseženi.</p>
<p>Psihofizični trening globokega sproščanja, ki ga izvaja, pogosto deluje na klienta kot podlago za osvobajanje napetosti, vendar kot psihoterapevt ne more zaobiti tudi ubesedene predelave problemov, ki so vzrok te napetosti. To pomeni, da je ponavadi nujno potrebno tudi psihoterapevtsko, na konflikte osredotočeno delo na sebi, ker se sicer globoko zakoreninjene zakrčenosti ne morejo trajno razrešiti. Samo globinska predelava, na primer, globlje ležeče tesnobnosti ali zadržane agresivnosti ali depresivnosti, lahko omogoči, da se psihični dejavniki, ki peljejo k telesnemu obolevanju, onemogočijo in da tako pride do prave spremembe, preobrazbe.</p>
<p>Psihoterapija je potemtakem način odkrivanja samega sebe, osvobajanja ran preteklosti, pristneje doživeti in zaživeti samega sebe ter dokončno pozdraviti rano.</p>
<p>»Psihoterapija pomaga ozavestiti omejujoče vzorce in strahove, ki smo jim v svoji notranjosti nenehno izpostavljeni, tudi če se jih ne zavedamo. Ko jih ozavestimo, se jih lahko osvobodimo. S tem pomagamo ranjenemu otroku, ki se zaradi negativne programiranosti skriva v vsakem od nas. Psihoterapija torej ne poudarja le zunanjega razvoja, temveč še bolj notranjega. Ker ta proces temelji na naravnih načelih zdravljenja, naj ne bi obstajala potreba po hitenju in težnji, da bi prišlo do spremembe čimprej. Vzeti si je potrebno dovolj časa in imeti je potrebno tudi pogum, da začne človek razvijati občutek za samega sebe in tako postane bolj zavedajoč samega sebe in duhovne razsežnosti svojega bitja« sklene Hermina Merc.</p>
<h3 class="section-title">PSIHOTERAPEVTSKE INTERVENCIJE V INTEGRATIVNI PSIHOTERAPIJI</h3>
<p>Integrativna psihoterapija se je oblikovala iz pomembnih izvorov geštalt terapije (Perls, Petzold) in madžarske aktivne psihoanalize (Ferenczi, Balint, Iljine), ter bihevioralne terapije in psihodrame (Moreno) v okviru »Fritz Perls Instituta« iz Nemčije (Hilarion Petzold).</p>
<p>Vsaka psihoterapija je narejena po meri, je enkratna. Obstajajo pa temeljni vzorci. Te temeljne vzorce, dinamiko in celotni potek integrativne psihoterapije lahko prikažemo z modelom, ki ga je izdelal/ utemeljil Hilarion Petzold.</p>
<p>Integrativna psihoterapija (IT) se v bistvu opira na štiri temeljne človekove sposobnosti. Razvoj teh sposobnosti je zmeraj hkrati cilj in vsaj v minimalni meri predpostavka terapije:</p>
<ul>
<li>1. korespondenca človeka z njegovim socialnim in ekološkim okoljem (kdor je v »slabem okolju« in odnosih zbolel, se lahko v dobrem izboljša ali celo ozdravi);</li>
<li>2. spontani, kreativni potencial, človekove sposobnosti zaznavanja, izražanja in oblikovanja ter sposobnost preizkušati nekaj novega;</li>
<li>3. sposobnost ekscentričnosti, kar pomeni sposobnost zavestnega doživljanja samega sebe ter okolja v preteklosti in sedanjosti, zmožnosti refleksije in relativiranja ter s tem vsaj v domišljiji zmožnost razvijanja alternativnih zamisli brez izgube usmerjenosti k sedanjosti. Z več ekscentričnosti postane jasnejše zavedanje o potekih v samem sebi, o razpoloženjih, telesnih občutkih in željah če jih lahko ubesedim, povečam s pomočjo govora svoje zavedanje samega sebe (sposobnost introspekcije, zavestnost), morebiti tudi intenzivnost svojega razpoloženja. Od neke stopnje ekscentričnosti pa postane nevarno, da spet izgubim stik s samim seboj, v katerem se potem zaznavam bolj »pri opazovanju« kot »pri čutenju«. Na ta način pridemo potem priložnostno do neavtentičnih stanj in izjav, ki so vir mnogih psiholoških šal, na primer: »Sedaj občutim, da sem strašno jezen nate«, namesto: »Poslušaj, to gre sedaj predaleč!«</li>
<li>4. sposobnost človeka za regresijo, ta omogoča emocionalno vrnitev v zgodnje scene in odnose, »kot da bi bili danes«, ter s tem odpira možnost novih emocionalnih izkušenj na ozadju starih scen. Ta način emocionalnega razumevanja (uvid) presega zgolj kognitivno razumevanje.</li>
</ul>
<p>Za ustvarjalne procese in tudi za integrativno psihoterapijo je odločilnega pomena oživljanje zgodnejših oblik doživljanja. Razrahljanje realitetne zapore nam daje možnost, da se vrnemo v zgodnejšo resničnost in gremo v prihodnjo resničnost. Lahko se vrnemo v ta zgodnejša stanja, ker so ta stanja ohranjena v nas. Shranjeno pa je tudi stanje, v katerem smo bili »pred regresijo«; pavšalno bi lahko rekli: »naša odrasla osebnost«.</p>
<p>V tem smislu regresija nikoli ni totalna razen pri organsko pogojeni regresiji. »Kasnejše« stanje vedno ostane prisotno v nas. To moramo upoštevati pri delu z regresivnimi klienti ali z regresivnimi tehnikami.</p>
<p>Regresija je mnogopomenski pojem. Poglabljanje v IT zajema predvsem dva vidika koncepta regresije: intenziviranje čustev v regresiji in preko regresije oživljanje starih scen. Koncept poglabljanja se ne nanaša na regresijo kot obrambo in tudi ne na regresijo kot držo. Čeprav je terapevtski odnos sam regresivno obarvan (»naknadno starševstvo«), ne govorimo o poglabljanju, temveč o regresivni strukturi odnosa.</p>
<p>Poglobitev je v terapiji zmeraj začasna in hotena. Če ima klient dovolj zaupanja v terapevta in se čuti varnega, je v stanju, da na podlagi čustvenega proučevanja svoje biografije, predvsem svojih doslej bolečih izkušenj, zrahlja nadzor nad sedanjo situacijo (svoj normalni varnostni sistem) in da znova oživi in preživi zgodnje scene. »Regresija« pri tem ne sega prav daleč nazaj: obstajajo neobvladane, čustveno nabite travmatske scene in izkušnje odraslih, ki morajo biti prav tako predelane kot izkušnje iz otroštva.</p>
<p>Pogosto pridejo klienti tudi že sami zelo močno involvirani na srečanje, denimo, zelo besni ali v solzah. To se prej zgodi v dolgotrajnih terapijah. V takšnem primeru mora terapevt začutiti in proučiti, kako daleč je ta čustvena involviranost »spontana poglobitev« oziroma ali gre za involviranost v zgodnje scene in/ali kako daleč je to izraz akutne odnosne motnje do terapevta ali do drugih ljudi.</p>
<p>Dogaja pa se tudi, da klient v prvi ali v prvih urah »izgubi prisebnost«, na primer zato, ker je končno »smel porušiti jezove«. To je intenzivni vstop v terapijo, terapevt mora to razumeti in delovati pomirjevalno, nikakor pa ne zaviralno. Nikakor pa terapevt v začetni fazi terapije ne sme delati v smeri, da bi sprožil takšno močno involviranost.</p>
<p>V končni fazi terapije so redka globoka regresivna dela, lahko pa pride do intenzivnih neregresivnih čustev, na primer kot je hvaležnost, radost novega začetka ali žalovanje zaradi slovesa.</p>
<p>Končno lahko v vseh fazah terapije nastopijo vse intenzitete čustev. Potrebno pa je dojeti kontekst, če naj jih tudi razumemo kot poglabljanje v pomenu regresivne involviranosti.</p>
<h3 class="section-title">O PSIHOTERAPEVTSKEM RAZUMEVANJU</h3>
<p>Pri predstavitvi terapevtskega procesa in terapevtskih intervencij smo se osredotočili na proces pri klientu. Pa vendar je pomembno poudariti, da v tem procesu sodelujejo celotno vedenje terapevta, njegove celotne življenjske izkušnje, profesionalna kompetenca in suverenost ( samovrednost, samoučinkovitost, mojstrstvo, avtentičnost, odprtost in širina misli, koherenca in fleksibilnost meja, lahkotnost, pokončnost, sprejemanje izzivov, modrost), njegovo terapevtsko orodje (fleksibilna strategija intervencij, diferencialna tehnika zdravljenja), njegovo znanje in osebna involviranost.</p>
<p>S terapevtskega vidika je pomembno mesto prehoda iz reda v kaos od kontinuitete do diskontinuitete, ki pomeni upanje za naš trud. Tukaj je točka, kjer je možna sprememba in prestrukturiranje, kajti natančno tukaj, »daleč od doseženega ravnotežja«, kjer je končno z minimalnim naključnim dogodkom odpravljena dolgoročna preračunljivost, se lahko zgodi sinergična samoorganizacija. Čeprav je kaos zmeraj nevaren, je tudi očitno neizogiben sestavni del vseh življenjskih procesov vedno takrat, kadar okamneli izmenjalni vzorci (na primer loputanje z vrati, kričanje naokrog, jok v postelji) nekega sistema trajno ovirajo razvoj boljših oblik interakcij.</p>
<p>V tem smislu pomeni psihoterapija pomoč pri odrekanju zastarelih načinov pri preživetju v kaosu in pri razvoju novega.</p>
<p>Kako daleč se nam terapevtom to posreči, je odvisno med drugim od našega pravilnega zaznavanja procesa: na katerem mestu neke razvojne spirale je klient sedaj? Ali je klient v fazi kaosa ali reda? Ali trpi, ker se oklepa nekega zastarelega reda, ki se sicer da razumeti iz njegove zgodbe, ki pa sedaj več ne ustreza? Kako zelo se ga oklepa? Ali popolnoma neomajno ali pa so opazna znamenja, da se toge strukture rahljajo?</p>
<p>Pomembni vidik, ki ga tudi moramo upoštevati, je naslednji: ali z našim delom podpiramo dosedanji red, ki ga je branil klient, ali pa podpiramo v poizkusu odrekanja prav ta stari red. Včasih lahko zato šele pozneje, iz učinka spoznamo, kaj smo podpirali: del klienta, ki pravzaprav hoče naprej, ali tisti del v njem, ki se bojuje za ohranitev dosedanjega reda.</p>
<p>Upanje ima več obrazov: tudi če je terapevt razmeroma prepričan, da bi njegova intervencija sprožila preobrat, bi moral premisliti, ali pri tem sledi le svoje lastne upe ali dela v dobro klienta.</p>
<p>Psihoterapija je proces, ki spreminja pogled na samega sebe.</p>
<p>Klient pa v začetku sploh nima tega cilja, temveč ima namen ohraniti svoj koncept Jaza natančno takega, kot je, vendar brez trpljenja, ki ga ta povzroča. Vse njegovo ravnovesje temelji na upanju, da je to mogoče. Klient upa, da se bo naučil doseči spremembe, ki jih sam hoče, ne da bi bistveno spremenil svoj koncept Jaza, in da bo vanj vključil še magično moč, ki jo išče v psihoterapiji. Klient brani svoje iluzije, ker vidi v njih svojo rešitev. Terapevta pogosto zaznava kot nekoga, ki napada njegovo najbolj varovano posest njegovo podobo o sebi. Ta podoba je klientova varnost, kot jo sam zaznava.</p>
<p>Na začetku si torej klientov in terapevtov cilj nasprotujeta, kajti ne glede na to, kako strokoven in iskren je terapevt, si terapevt želi spremeniti klientov koncept Jaza na način, ki ga ima sam za resničnega.</p>
<p>Naloga psihoterapije je, da tako klient kot terapevt, presegata te razlike in omejitve v začetnih ciljih, saj je rešitev mogoče najti samo v medsebojnih odnosih. Čim bolj se nam posreči delati »s tokom«, tem bolj zadovoljivo se izoblikuje delo med klientom in terapevtom.</p>
<p>Mogoče je, da psihoterapiji navidezno spodleti. Možno je celo, da je rezultat videti kot nazadovanje. Pa vendar vseeno prinese napredek.</p>
<h3 class="section-title">PREDSTAVITEV PSIHOTERAPEVTSKIH INTERVENCIJ V INTEGRATIVNI PSIHOTERAPIJI</h3>
<p>V integrativni psihoterapiji razumemo s psihoterapevtskimi intervencijami vso celoto postopkov, ki ponovno vzpostavljajo ali razvijajo omejeno korespondenco človeka, ki ni več kos samemu sebi in drugim.</p>
<p>Odkrivanje samega sebe in življenjskega sveta, soočanje z življenjskimi strahovi in iluzijami v sedanjosti, preteklosti in prihodnosti odpirata klientu v procesu integrativne psihoterapije vedno nove perspektive. Pri tem mu lahko pridemo na pomoč z raznolikimi sredstvi (terapevtskimi intervencijami, postopki, tehnikami), mu ponudimo različne medije, ki olajšujejo potovanje k samemu sebi, obenem pa spodbujajo zdravilne procese, če obstaja motnja ali bolezen.</p>
<p>Dobrih nasvetov, domnevanj in predpostavk o vzrokih svojih težav je verjetno klient slišal že dovolj. To mu ni veliko koristilo; morda nasveti niso bili dovolj dobri, morda je tudi on preveč zmeden, da bi kaj naredil z njimi, ali pa mu je situacija ostala nejasna. Zaradi tega je tudi prišel kot klient na psihoterapijo. Na veliko vprašanj klient ne more odgovoriti ali pa pogovor poteka nejasno. Torej mu moramo zastavljati tudi vprašanja, na katera lahko »nevede odgovori«, na primer, z mimiko obraza, kretnjami, držo telesa, načinom, kako vstopi v stik z nami, z reakcijami na našo prijaznost ali zadržanost ter z načinom, kako govori o stvareh, ljudeh in dogodkih ali o njih ne govori.</p>
<p>V IT je posebno pomembno doumeti, začutiti, kateri medij je primeren, da stopimo v stik z določenim klientom: zelo regresivnega klienta dosežemo v določenih okoliščinah le z dotikom ali zvokom glasu, ne pa z besednim sporočanjem; paničnega ali obupanega klienta morda le s telesnim stikom. Včasih dosežemo klienta tudi tako, da pokažemo svojo pripravljenost, da bomo ohranili veliko fizično distanco, ki jo na začetku potrebuje.</p>
<p>Včasih potrebujemo kot terapevti tudi predmete, s katerimi lahko vstopimo v stik, na primer intermedialne objekte, kot so živali iz blaga, lutke.</p>
<p>V terapiji nemalokrat pridemo v položaj, da klient » izstopi iz kontakta«, na primer, pri kočljivih temah ali pri naših prevelikih zahtevah.</p>
<p>To «iti iz kontakta« je pomemben kazalec za vrsto motnje in strahov klienta. Nekaterim klientom, predvsem tistim z zgodnjimi okvarami, je težko nepretrgano urejevati bližino in distanco. Iz potrebe »katapultirajo« v nenadnem aktu sile (pogosto agresivnem) spet v varnejšo oddaljenost. Tam se spet lahko vzpostavi čustvo osamljenosti in zapuščenosti. Ta nenadna in težko predhodno predvidljiva približevanja in distanciranja so lahko za terapevta zelo obremenjujoča in spravljajo tudi klienta samega v veliko negotovost.</p>
<p>Na tem mestu bodo navedene vse najpogosteje uporabljene terapevtske intervencije v IT.</p>
<p>V praksi jih lahko uporabljamo samostojno ali pa jih med seboj kombiniramo in/ali priredimo glede na dogodek, strukturo osebnosti in razvojne značilnosti ter posebnosti klienta, vrsto motenosti, smer zdravljenja in fazo terapevtskega procesa. Katere bodo izbrane pogosteje, pa je odvisno od profesionalne kompetence psihoterapevta.</p>
<p>Terapevtske intervencije IT:</p>
<ul>
<li>- usmerjanje pozornosti,</li>
<li>- ponavljanje,</li>
<li>- pretiravanje,</li>
<li>- asociiranje,</li>
<li>- vztrajanje,</li>
<li>- obračanje v nasprotno,</li>
<li>- delo na govornem izražanju,</li>
<li>- uporaba primerov,</li>
<li>- pretvarjanje preteklosti in prihodnosti v sedanjost,</li>
<li>- imaginacija vizualizacija,</li>
<li>- identifikacija,</li>
<li>- dialog igranje vlog,</li>
<li>- spreminjanje vedenja vloge,</li>
<li>- delo s kreativnimi mediji,</li>
<li>- delo s transfernimi in intermediarnimi objekti,</li>
<li>- telesne intervencije.</li>
</ul>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Usmerjanje pozornosti</h4>
<p>Klientovo pozornost usmerimo na občutke, misli, vedenjske vzorce, za katere terapevt meni, da so pomembni, pa čeprav klient misli, da niso ali jih niti ne doživlja zavestno.</p>
<p>Primer:<br>
Terapevt postane pri klientu pozoren na neskladja, predvsem med ubesedenim in nebesednim izrazom, občutenjem, in vanje usmeri njegovo pozornost:<br>
»Jezite se na svojega sina, ob tem pa se smehljate.«<br>
»S čisto tihim glasom ste rekli, da boste šefu povedali svoje mnenje.«</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Pretiravanje</h4>
<p>Pretiravanje uporabljamo bolj previdno, ker ima pogosto močan učinek in lahko izzove strah.</p>
<p>Množica tehnik IT rabi temu, da bi naredili klientove fenomene bolj izrazne in sprožili podobne fenomene ter se tako približali smislu, ne da bi ga prehitro določili.</p>
<p>Primer:<br>
T: »Nadaljuj z gibanjem nog in gibanje še okrepi. Kaj čutiš ob tem? Poznaš ta gib? Kaj ti ob njem pride na misel?«</p>
<p>Pri terapevtskem delu je torej govor o zaznavanju in razumevanju fenomena tukaj in sedaj. Med stopnjevanjem bingljanja nog klient zmeraj bolj zaznava, da je besen. Mogoče si bo takrat upal reči terapevtu: »Jezim se na vas, ker ste me sedaj že dvakrat pustili čakati, ne da bi se mi opravičili.« Šele z zavestnim zaznavanjem gibanja z nogami spozna, da je jezen.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Vztrajanje</h4>
<p>Ta tehnika je posebej važna v primerih, ko hoče klient nekaj na hitro preskočiti ali le bežno nakazati nekaj, kar ni jasno določeno oziroma bi po mnenju terapevta lahko bilo pomembno. Pogosto pomeni vztrajanje, spoznanje in sprejemanje težav ali občutka nemoči prvi korak v neko novo smer: nekaj, kar je bilo do sedaj tabu ali čemur smo se izogibali, nenadoma zaznamo ali dopustimo.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Tehnika obračanja v nasprotno</h4>
<p>Ta tehnika izhaja iz predpostavke, da so ekstremno vedenje, čustva, misli, vedenjski vzorci le ena plat medalje, da dva nasprotna pola kratko malo sodita skupaj. Zavzemanje ekstremnih stališč ni naključje. Zato je smiselno, da se poglobimo v skrajnosti.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Uporaba primerov</h4>
<p>Če se terapevt neposredno dotakne neke zadeve, občuti klient to včasih kot tesnobo. Če ima terapevt vtis, da klient nečesa ne bi mogel sprejeti v neposredni obliki in bi se uprl, lahko uporabi primere, zgodbe, basni, mite. S tem vzpostavi distanco in tako zmanjša odpor. Meje se znižajo, odpor se razblini, povedano je lažje dojemljivo.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Pretvarjanje preteklosti in prihodnosti v sedanjost</h4>
<p>S to tehniko preprečimo, da bi klient predolgo in morda neprizadeto govoril o preteklih in prihodnjih situacijah. Zaprosimo ga, da preteklost in prihodnost pretvori v sedanjost in o vsem pripoveduje tako, kot da bi vse pravkar doživljal. Poročilo tako postane pripoved, doživeta zgodba. Oživijo zdavnaj pozabljeni občutki, čustva, misli, vedenjski vzorci. Take intervencije pogosto pripeljejo zelo globoko in jih zato pazljivo uporabljamo. Tehnike ne uporabljamo le pri zelo oddaljenih dogodkih, temveč tudi pri zdajšnjih dogodkih, pri katerih gre za situacije, ki s terapevtskimi niso povezane.</p>
<p>To tehniko pa uporabljamo tudi pri delu s sanjami in pri terapevtskem delu glede na prihodnje situacije. Posebno kadar sta prisotna strah in brezizhodnost, lahko tehnika spreminjanja v sedanjost pripomore k lažjemu obravnavanju katastrofičnih slutenj ali konkretnih bojazni.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Identifikacija</h4>
<p>Identifikacija je sposobnost vživljanja v drugačne vloge, predstave, pomeni sposobnost prehodne drugačnosti. Identifikacija je osnova za vse igre z vlogami in tehnike dialoga. S pomočjo identifikacije lahko razjasnimo misli in dejanja. Terapevt, denimo, predlaga klientu, naj si predstavlja, kaj bi povedala stisnjena pest, če bi znala govoriti; ali pa naj postane cmok v grlu ali drevo, ki čuti korenine. Za klienta je identifikacija s pomočjo predstave pogosto nenavadna. Ta tehnika je zelo primerna tudi za delo s kreativnimi mediji in za delo s sanjami.</p>
<p>Identifikacijski objekti so lahko:</p>
<ul>
<li>- druge osebe,</li>
<li>- deli telesa,</li>
<li>- čustva, misli, dejanja,</li>
<li>- sanje, ideje, predstave,</li>
<li>- predmeti.</li>
</ul>
<p>Primer:<br>
K: Včasih si sebe predstavljam kot velik, močan vulkan, ki se ga vsi bojijo.<br>
T: Predstavljaj si, da si sedaj vulkan… in reci: Sem velik, močan vulkan.<br>
K: Imam strašno moč in lahko vse porušim, vsi trepetajo pred menoj. Vsak čas bi lahko izbruhnil, zato se mi nihče ne upa približati.<br>
T: Kakšen občutek je to, biti mogočen, strašen vulkan?<br>
K: Dober. Se mi vsaj nič ne more zgoditi.<br>
T: Nič?<br>
K: No ja, v bistvu sem vendar votel, lahko bi se sesul vase in iztekel… (Klient joče in reče: V bistvu je ta moja moč le fasada.)<br>
T: V resnici ste čisto drugačni, krhki in ranljivi?<br>
Tehnika identifikacije je zelo primerna za terapevtsko delo pri odporu. Omogoča spoznavati odpor in razreševati stare, zatrdele vzorce.<br>
Kadar klient ne more z določene točke, ga prosimo, da se identificira s trenutnim ozračjem, občutjem, na primer, ko klient reče: »Okoli mene je zid, ne morem čezenj, čeprav si vsakič rečem, da bom tokrat vsaj pogledal tja čez, okoli mene je prava zmešnjava,« mu lahko predlagamo, naj postane ta zmešnjava.</p>
<p>V nadaljevanju lahko izdelamo načrt, ob kakšnih pogojih bo zid lahko popustil. Odpor razumemo kot obrambo pred strahom, da ne bi postali preplavljeni s čustvi, ki ne morejo biti premagana, in s tem tudi kot obrambo pred strahom do sprememb. V določenem življenjskem kontekstu so bile obrambe življenjsko potrebne. Ko pa ne reagirajo na spremenjene življenjske razmere, temveč so toge, nefleksibilne, trde še naprej, ovirajo živahnost in razvoj človeka. Za delo pri odporu oziroma raztapljanju odpora je pomembno, da:</p>
<ol>
<li>akceptiramo odpor, da ga sprejmemo, da imamo spoštovanje pred odporom in smo pazljivi z našo interpretacijo o obrambnih strukturah. Res pa je težko vedno sprejeti odpor, ko vidimo, kako od zunaj deluje samouničujoče.</li>
<li>Razumevanje odpora pomeni, da ga imenujemo, razjasnimo, ga okrepimo in da pustimo, da v svoji nastajajoči zgodovini scensko oživi. Odpor naj bi bil, če je le mogoče, ogovorjen in konkretiziran, sprva neodvisno od tega, kako se kaže ali v čem se pusti ujeti. K razumevanju odpora, blokade spada tudi sprejeti dejstvo, da meje obstajajo in da ni vse mogoče, torej ne zgolj sprejeti klientov »ne še« ali »ne tako«, temveč mogoče tudi »sploh ne«. Največji učinek je lahko v tem, da skupaj žalujeta. In lahko se zgodi, da bo prav tedaj trda struktura popustila.</li>
<li>Ustvarjanje varnosti<br>
K ustvarjanju varnosti sodi to, da terapevt za vsakega klienta posebej razvije občutek za hitrost, obliko in količino. Klient potrebuje zadostno število izkušenj, da se lahko približa tistemu, kar mu je sedaj težko, začutiti mora varnost glede trajnosti in stabilnosti terapevtskega razmerja. »Še naprej me bo marala, tudi če jočem/ stresam svojo jezo nanjo/ če ne napredujem/ če ponovno razvijem psihosomatske simptome.«<br>
Dobra možnost pri terapevtskem delu zoper odpor obstaja tudi v tem, da kadar je nekaj pretežko, to olajšamo »znižamo valove«.</li>
</ol>
<p>Primer:<br>
K: Svojemu očetu tega ne morem povedati.<br>
T: Ali bova vadili po vlogah?<br>
K: Tudi tega ne morem.<br>
T: In če sedem poleg tebe?<br>
K: Potem ni tako hudo, a še vedno ne morem povedati.<br>
T: Naj jaz govorim namesto tebe?<br>
K: Ja, to bi bilo dobro, toda jaz sem pozabila, kaj sem mu nameravala reči.<br>
T: Jaz sem si zapomnila.</p>
<p>Druga možnost razvijanja občutka varnosti je v tem, da si strah in bojazni ogledamo od blizu: kolikor bolje nekaj poznam, toliko bolje si lahko to razlagam. Nekateri strahovi se lahko omilijo takoj, ko postanejo jasni in znani. S kreativnimi mediji, z identifikacijami in/ali v igrah vlog je moč strahove dobro razjasniti.</p>
<p>V primerih deficitnih izkušenj, manjkajočih priložnosti, pomanjkanja eksperimentiranja, vaj, naletimo pogosto na odpor, ki morda ne more biti rešen zgolj zato, ker je napaka v spodbudi, na primer, da se terapevt omeji na en medij (na primer »samo na govor« ali »samo na gibanje«) ali na set. Določene izkušnje so lahko vzbujene ali se razvijejo samo v določenem okolju, denimo, delo še z drugimi mediji, igra vlog, drugi seti, kot skupinska terapija namesto individualne ( to se tiče profesionalne fleksibilnosti terapevta).</p>
<p>V nekaterih okoliščinah je primerno, da terapevt sam prevzame odgovornost in da klienta kljub sedanjemu odporu ( kratkoročno oropan svojega strahu) vseeno »prisili« k zadovoljstvu: pravimo, da včasih pomaga »sunek vetra z vedrega neba«, dokler namreč terapevt ve, da klient zna plavati, da mu od strahu ne bo zastal dih in da mu lahko vsak trenutek ponudi roko. Pri tej vrsti ukrepov naj bo obema jasno, da gre za resnično anahronistični odpor, ki je že preživet, a vztrajen in skrajno pust.</p>
<p>Primer: Sedaj pokliči! Jaz bom počakala v sosednji sobi. Vem, da to lahko storiš!<br>
Manj drastično je, če odgovornost za skok prevzameta oba, terapevt pa vliva klientu pogum, da prevzame tudi tveganje.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Dialog igre z vlogami</h4>
<p>K tehniki dialogov iger z vlogami (tehnika »praznega« stola) sodijo tudi vse tehnike psihodrame. Predpostavka za vse tehnike je identifikacija: le če sem sposoben vživeti se v drugačne vloge, predmete, dele telesa in podobno, lahko vzpostavim smiselni dialog z medsebojnim pogovorom, pojasnjevanjem, zbliževanjem.</p>
<p>Kadar delamo s tehnikami vlog, se neposredno dogaja nekaj drugega kot pri sami pripovedi. Z identifikacijo klienta z nasprotno osebo, s katero je v stiku in razglablja pri igri z vlogami, lahko klient to osebo občuti in doživi.</p>
<p>Denimo, ko se klientka identificira s svojo ubogo, večno depresivno materjo, se nenadoma zave, kolikšno moč jej daje ta vloga. Ali pri igri z vlogami poskuša izraziti občutke, ki jih je do sedaj skrivala. Na primer, da ima nekoga rada, v komplementarni vlogi pa izve, da ga je do sedaj le zapostavljala in se izogibala potrebnemu medsebojnemu pogovoru. Ali pa spozna užitek, ki ji ga daje trma.</p>
<p>Mnogi klienti v »tuji« vlogi naravnost oživijo, kajti le-te vedno vsebujejo del njih, del, ki ga do sedaj ni bilo možno integrirati.</p>
<p>Igra z vlogami daje zelo raznolike možnosti. Klient lahko igra prizore iz svojega življenja, s tem oživlja ozračje in konkretizira spomine. Lahko se poglobi v čustva, ki jih je do sedaj odrival. Ali pa igra situacije iz sedanjosti, ki jih ni mogel obvladati. Ali pa »iznajde« vloge, ki bi jih rad dosegel.</p>
<p>Tudi terapevt ima nešteto možnosti pri oblikovanju vlog. Lahko, denimo, podpre klienta, ko se pripravlja na vlogo (s konkretiziranjem, pojasnjevanjem, intenziviranjem s pomočjo že opisanih intervencij), postavi se h klientu, zato da bi ga podprl, mu pomagal pri pripovedovanju, česar si mogoče klient ne upa niti pomisliti, kaj šele izreči.</p>
<p>Terapevt pa lahko tudi sam prevzame neko vlogo, jo oblikuje itd.</p>
<h3 class="section-title">KREATIVNI MEDIJI V IT</h3>
<p>Pri uporabi tehnik s kreativnimi mediji je teoretično ozadje za klienta zelo pomembno, zato mu je smiselno razložiti, zakaj je uporabljen določen medij, na kakšen način je terapevtsko delo s kreativnimi mediji podpirajoče, ozdravljujoče. Tako klient ne bo v sebi postal razdvojen, da je vedno znova predmet manipulacije ali slepe pokorščine, ki ne ponuja nobenih možnosti za sodelovanje razen prilagajanja, podrejanja ali reakcije odpora.</p>
<p>Izhajamo iz tega, da klienti, ki dobijo dober teoretični uvod v psihoterapevtske intervencije, v terapiji bolje sodelujejo, začetna raven odpora je nižja in tako so v celotnem poteku psihoterapije bolje opremljeni za to, da se spoprimejo z odpori in obrambnimi reakcijami.</p>
<p>Delo s kreativnimi mediji v IT zajema iste medije, ki veljajo tudi v umetnosti:</p>
<ul>
<li>- barvice,</li>
<li>- glina za gnetenje,</li>
<li>- zvok, glas, glasba,</li>
<li>- glasbila,</li>
<li>- fotografije iz življenjskega sveta,</li>
<li>- lutke, plišaste živali,</li>
<li>- pripovedovanje pravljic, pripovedk, legend, mitov, basni, zenovskih zgodb,</li>
<li>- maske za pantomimo,</li>
<li>- sanje, vizualizacija,</li>
<li>- ples gibanje,</li>
<li>- pisanje pisem.</li>
</ul>
<p>Vsi mediji vsebujejo različno moč izražanja in imajo svojevrsten odziv na klienta. V terapevtskem delu s kreativnimi mediji, vodeno fantazijo, sanjami in podobnim, neposredno spodbujamo celostno čutenje, razumevanje, odzivanje, na primer, da napišejo na pravkar narisano risbo pesem ali da najdejo glas ali zvok k zadržanju ali kretnji.</p>
<p>Dostop k nezavednemu je pri terapevtskem delu s kreativnimi mediji navadno veliko bolj neposreden kot pri terapevtskem delu z govornim izražanjem. Ponavadi je tukaj tudi lažje delati z odpori, ker odpore »zaobidemo«.</p>
<p>Mnogi odrasli morajo premagati prag bojazni, ki je socializacijsko pogojen, in so šele nato pripravljeni na delo s kreativnimi sredstvi. Pozorni smo na to, da smo pri uvajanju kreativnih tehnik razumevajoči do morebitnega pojavljanja strahu ali občutij tesnobe.</p>
<p>Na primer, kadar nekdo prvič dela z glino, lahko tudi terapevt vzame v roko kos gline in pove, da je treba glino najprej ogreti in zgnesti, spoznati.</p>
<p>S pomočjo gline pogosto izzovemo regresijo, lahko oživijo zgodnji arhaični občutki in prizori, predvsem kadar delamo z zaprtimi očmi in brez strukturno naglašenih elementov.</p>
<p>Regresivno delo z glino zahteva stabilen odnos med klientom in terapevtom.</p>
<p>Glina je primerna za izražanje močnih občutij jeze, sovraštva, veselja in podobno. Glina je tudi medij za obravnavo govornih blokad, prisilnih posledic vzgoje k čistosti in pomanjkljivih izkušenj z telesom.</p>
<p>Če damo navodilo, naj izdelajo družinsko skulpturo, in jo imamo za izhodišče pri delu z vlogami, potem je pri tako drugače strukturiranem izhodišču regresija manj verjetna.</p>
<p>Če želimo, da klient ozavesti in poišče podporo v samem sebi in v življenjskem svetu, ga prosimo, naj naslika potenciale, vire moči tako, da v velik krog vriše vse, kar je zanj življenjsko pomembno in v čemer najde oporo: denimo, ljudje, znanje, dobrine, zdravje, vrednote,…, in naj nato izrazi pomembnost zanj z barvo, simbolom,…</p>
<p>Pri slikanju »telesne sheme« leže klient na velik kos papirja, terapevt pa izriše njegove obrise. Telesno shemo poslika nato klient sam. Ob tem pridejo do izraza deli telesa, tabuirani deli, identifikacija, telesna samopodoba, »otoki telesa« ter zavedne in nezavedne predstave o samem sebi.</p>
<p>Delo s kreativnimi mediji lahko še poglobimo, kadar jih kombiniramo; na primer, občutke narisane panorame lahko nato klient izrazi tudi v obliki pesmi, ki jo lahko napiše ali zapoje.</p>
<p>Za terapevtsko delo s kreativnimi mediji pa je seveda pomembno, da je na voljo dovolj časa.</p>
<p>Ob delu klienta s kreativnimi mediji ima tudi terapevt veliko možnosti. Lahko je le prisoten, lahko prevzame govorni kontakt, kreativno sodeluje (oblikuje velik kos gline in ga ponudi klientu za njegovo produkcijo). Pri igri z lutkami, denimo, lahko terapevt prevzame vlogo, ki si jo je izbral sam ali pa mu jo je izbral klient.</p>
<h3 class="section-title">POMEN PREHODNIH OBJEKTOV</h3>
<p>Intermediarni objekti so mostovi, pomočniki za vzpostavitev povezave, še posebej, ko neposredna komunikacija ni mogoča.</p>
<p>Prehodni objekti so predmeti, ki so praviloma mehki in oprijemljivi, ki so dosegljivi ter so povezani s prijetnimi izkušnjami. Ti predmeti imajo v otroštvu nalogo, da ublažijo in omogočajo preživeti frustracije, ko je otrok sam, in so tolažilni.</p>
<p>V razvojni psihologiji so prehodni objekti opredeljeni kot »tolažitelji«, kot zaupniki, kar otrok mora imeti pri sebi, da zaspi, da prenese odsotnost matere: krpa, medvedek, jopica, ki diši po materi, slika psa, živa želva itd. Intermedijski objekti so kot mostovi, pomagala, ki pomagajo navezovati vezi, kadar ni možna medčloveška komunikacija.</p>
<p>Prehodni objekti so pomembni tudi pri terapevtskem delu, med drugim lahko tudi zelo konkretno ponazorijo stabilnost v odnosu (emocionalna varnost, ponotranjeni odnos, občutek večje avtonomije).</p>
<p>V IT jih uporabljamo v dvojni funkciji: da bi navezali in obdržali vezi med klientom in terapevtom ter da bi klientu pomagali pri zgodnjih spominih in scenskih doživljanjih.</p>
<p>Navezujoč se na pripoved klienta o določeni temi, lahko vprašamo, ali se spominja, kaj je imel za tolažbo, s čim je lažje zaspal, kaj je občutil ob odhodu matere, očeta itd. Spomini postanejo konkretnejši in živi, če si klient predstavlja, kakšen je bil zajček (otip, vonj), ko ga je mama oprala, ko se je izgubil, ko je bil podarjen. Scenski spomini se še poglobijo, če zajec »živi« in ga prinese k terapiji. Zajec postane intermedijski objekt, ko sprašujemo, kako se je klient z njim igral, kaj mu je govoril, kaj mu je on odgovarjal, kaj je mati spraševala zajca, kadar ji sin ni hotel odgovarjati.</p>
<p>Prehodni objekti pa niso le plišaste živalce. Neka klientka je pripovedovala, da je iz strahu pred dedkom zvečer oživljala zavese, omare in druge predmete, da ne bi bila sama. Pomembni prehodni objekti so tudi palec, prijemanje za nos ali uho, sukanje vogala posteljnine.</p>
<p>Potreba po prehodnih in intermediarnih objektih zelo jasno kaže na deficite.</p>
<p>V medosebnih odnosih med klientom in terapevtom so intermedijski objekti pomembni, kadar obstaja bojazen, da bo stik pretrgan, ali kadar nečesa ni mogoče izgovoriti; takrat lahko pomagajo in so lahko most k nastajanju odnosa. Včasih si lahko terapevt in klient preko prehodnega objekta povesta nekaj, česar (še) ni mogoče izreči, sprejeti neposredno.</p>
<p>Včasih je prehodni objekt skupaj popita kava ali čaj v tem smislu: Razumem vaš strah pred vsem tem, čaj je v tem trenutku edina možnost, da sva skupaj, to daje dovolj varnosti in potrebno distanco.</p>
<p>Pri terapevtskem delu tudi kreativne medije razumemo kot intermedijske objekte.</p>
<p>Prehodni objekti so predvsem v fazi regresije pomembni, kadar si klient še ni dovolj na jasnem, da lahko odnos vztraja določen čas. Po eni strani ga prehodni objekt tolaži, po drugi pa mu pomaga preživeti neko dozdevno dolgo obdobje: v fazi regresije se zdi, na primer, pet dni do naslednjega termina težko pregledno dolgo obdobje.</p>
<p>Primer:<br>
Ustvarjanje varnosti: Klient si lahko od terapevta nekaj sposodi: knjigo, kaseto, plišasto živalco.<br>
Klient dobi telefonsko številko terapevta, da ga lahko pokliče tudi med počitnicami, dogovori se o tem, koga še lahko pokliče za pomoč, o nadaljnjih terminih.</p>
<p>Paziti je potrebno, da »prehodne« ponudbe ustrezajo obema in ne povečujejo odvisnosti klienta. Ne smemo jih vsiljevati. Prav tako jih ne smemo uporabljati, da bi z njimi preprečili, na primer, slovo, žalovanje in podobno.</p>
<h3 class="section-title">TEHNIKA PANORAME</h3>
<p>Človek bi moral v tem, kar ve o sebi, imeti na voljo spomine na otroštvo. Zato ni pomembno raziskovanje otroštva in mladosti, pozabljenega, potisnjenega samo z vidika patogeneze, da bi torej prišli do zavesti o obremenjujočih in škodljivih vplivih, ki imajo za posledico motnje vedenja ali osebnosti, temveč je to raziskovanje veliko bolj pomembno z vidika zdravja (salutogeneza v IT), torej kot vedenje (znanje) o »dobrih izvorih« lastne biografije.</p>
<p>Benigne otroške izkušnje, izkustva varnosti, trdnosti, veselja, igre in praznovanja, določajo naš življenjski občutek.</p>
<p>Pomemben instrument, ki povezuje diagnostične in terapevtske vidike (teragnostični instrumentarij v IT), in ga je razvil Petzold ter rabi klientu za dostop do pozitivnih socializacijskih vplivov, ki odpirajo osebnostne vire, je metoda Življenjske panorame oziroma Triplastne panorame kariere, ki zajema pozitivne, negativne in deficitarne vplive.</p>
<p>Pri Življenjski panorami, pri Panorami zdravja in pri Panorami bolezni ter pri Triplastni karierni panorami, klient slikovno upodablja:</p>
<ul>
<li>- verigo kritičnih dogodkov, rizične faktorje in negativne življenjske dogodke,</li>
<li>- verige zaščitnih, podpornih, ozdravljajočih vplivov v njegovem življenju,</li>
<li>- podaljšane izkušnje primanjkljajev, verige deficitov glede na socialno okolje.</li>
</ul>
<p>S tem instrumentom panorame omogočimo razumevanje konfliktnih polj, konfliktnih jeder, konfliktnih konstelacij in tudi deficitov ter travmatiziranja oziroma motenj in diferenciranja. Uporaba panorame rabi za podporo klientu, ko razlaga svojo življenjsko pripoved, ki se dotakne klienta. Usoda in trpljenje klienta pa se na svojevrsten način dotakneta tudi terapevta, ki pri tem uporabi svojo poklicno in življenjsko modrost. Klientu lahko ponudimo vzpostavitev »poskusne scene« iz upodobljenega gradiva in poizkus »poskusnega insceniranja«, na primer, ponudimo »prazni stol« ali »izmenjavo vlog«.</p>
<h3 class="section-title">VPRAŠANJE DOTIKA V INTEGRATIVNI PSIHOTERAPIJI</h3>
<p>Telesni dotik in intervencije so sestavni del psihoterapevtskega dela v IT, saj je osrednji koncept IT telesnost in korespondenca. V kolikšni meri dojamemo, da in kako zelo so zgodnji temeljni odnosi in s tem tudi temeljne poškodbe povezane s telesnostjo, v tolikšni meri moramo tudi integrirati v našo terapijo telesni vidik odnosov. Le tako ne bomo tvegali, da bi nastale nove razcepitve ali ponovna brezodnosnost.</p>
<p>Telesni koncept IT poudarja, da so vsi naši odnosi, naši stiki pravzaprav telesni. Medij stika z našim okoljem je naše telo, posebno naša koža. Naše telo je temelj in hkrati model za vse izkušnje meje. Toda tudi drugi čutni organi, predvsem oči, se dotikajo in razmejujejo (stik z očmi, odklonilen pogled, srečanje s pogledi). Vse te telesne funkcije so bolj ali manj močno pod vplivom medčloveških odnosov in tudi vplivajo nanje. Telesne funkcije lahko s tem izrazijo neposredno ali posredno, simbolično motnjo v odnosih (na primer: »Ko jo vidim, me začne mraziti«; »Pred vsakim izpitom dobim drisko«.). Česar človek ne more izraziti v odnosu do sveta (na primer žalost) ali ne more aktivno spremeniti (na primer z jezo, gnevom), se v določenih okoliščinah izrazi v njegovem telesu ali na njem.</p>
<p>Fundamentalni del naše vzgoje (socializacije) se dogaja v obliki nadzora telesnih funkcij: sedenje pri miru, da se ne pretepaš, ne rigaš, vzdržuješ pravilno distanco najprej kot telesno razdaljo, kasneje tudi simbolično z nagovorom, izbito besed in podobnim.</p>
<p>Tudi naša identiteta, »kdo smo«, kakšno vlogo igramo, se izraža telesno z načinom, kako se gibljemo, kako govorimo, se oblačimo. Celoto teh socialno pogojenih načinov vedenja imenujemo v IT »socialno telo«. Torej ni interakcije brez telesa!</p>
<p>Izrazno vedenje človeka je v veliki meri podrejeno socialnim vplivom (socialne samoumevnosti, ki jih niti ne dojemamo kot norme) in nezavedni »socialni okužbi«; denimo: »Tiho moram biti zaradi sosedov«, »Žalost sicer lahko občutim, a je ne smem pokazati, da ne bi vznemiril svoje matere«. Nerešeni notranji konflikti ( na primer konflikt med »udariti« in biti »ljubezniv«) se pogosto izražajo v telesni obliki ( na primer »ohromitve«).</p>
<p>Telesni spomin v IT ni »drugačen spomin«, temveč pomeni spominske sledi telesnih dogodkov.</p>
<p>Kajti spomin ne vsebuje le podob in tonov zaznanega prizora ter besed ali stavkov, temveč tudi k prizoru pripadajoče telesne občutke, napetosti, gibalne impulze ali impulze za dejavnost in zadržanja. Povezava med prizorom in telesnimi občutki se lahko izgubi, izrine, pozabi ali avtomatizira, telesni impulz, telesni občutek pa se lahko ohrani. »Spomin pesti«, ki se izraža v bolečini, je v terapiji zelo pogosto izhodišče za rekonstrukcijo, ponovno doživetje celotnega prizora z vsemi deli občutka in s tem povezanih možnosti za rešitev napetosti in blokade.</p>
<p>Kaj so telesno terapevtske intervencije?<br>
Telesni stiki se v IT kažejo po eni strani bolj kot funkcionalni dotiki v okvirih telesno terapevtskih intervencij, po drugi strani pa tudi izhajajo neposredno iz odnosa med terapevtom in klientom, iz doživetja stika.</p>
<p>Kadar klientu, ki mi pove, da »čuti neznosen pritisk v prsih«, vendar ga ne more »pokazati«, pritisnem svoje dlani na prsni koš, postane njegova senzacija bolj izrazita.</p>
<p>Ali na primer, kadar klienta, ki ima izredno močne krčevite bolečine v vratu, prosim, da drži vrat še bolj togo ali pa mu rečem: »Sedaj se bom dotaknila vašega vratu, prav? In če vam bo kakorkoli neudobno, prosim, povejte. Kako se počutite?«</p>
<p>In če klient, denimo, odvrne: »Mislim, da…«, bi bila moja intervencija: »Aha, mislite! Začnite premikati glavo v desno in levo stran (in mu pomagam, tako da mu z rokami premaknem glavo v levo in v desno), tako boste lažje prišli ,ven iz glave'.«</p>
<p>V resnici jih namreč razdraži to, da bi premikali glavo L - D in še razmišljali ob tem. V tem primeru z gibanjem glave klientu pomagamo priti iz razmišljanja v stik s čustvovanjem, nima pa to zveze z regresijo.</p>
<p>Ali ko mlada klientka govori o strahu pred stiki, pred dotikom, pred življenjem, in pripoveduje o očetu, ki ji ni dovolil, da je živa, in da se zato še sedaj nadzira in je na preži, da se ne bi izrazila, jo povabim, da lahko pride bližje k meni: »Lahko sedeš bližje k meni, kolikor želiš.« In ko odkima, ji predlagam: »Dovoli, da pridem jaz bližje k tebi.« Sedem k njej in jo primem za roko. Klientka se zdrzne in vprašam: »Kaj ti moj dotik pomeni?« »Prosim, povej mi ali vsaj pokaži.«</p>
<p>K: »Strah me je.«<br>
T: »Pokaži to!«<br>
Klientka odmakne svojo roko.<br>
T: »Kako se počutiš?«<br>
K: »Ne želim nič čutiti. Potem se izgubim. Moram imeti vse pod kontrolo.«<br>
T: »Veš, jaz te nočem razbremeniti kontrole, saj vem, da je kontrola tvoj najstarejši poznani (domači) prijatelj. Lahko pa ti pomagam, da spoznaš sebe, svoje želje in da začutiš svoje potrebe. Potem te lahko tvoje potrebe zaščitijo pred preveliko kontrolo. Želiš to?«</p>
<p>Telesni dotiki iz odnosa pa se kažejo neposredno, iz doživetja stika terapevta, iz intenzivnih senzacij in čustev klienta, njegovega strahu, izgubljenosti, besa, žalosti ali veselja, torej iz čustvene prizadetosti. Čisto spontana človeška kretnja je, kadar primem klienta, ki je v scensko doživetem slabem soočenju s svojo materjo jokal od žalosti in izčrpanosti. Vendar si moram biti kot terapevt na jasnem o pomenu le-tega in o možnih posledicah!</p>
<p>Velikokrat se znajdemo v tabuiziranem področju telesnega stika. Zdravniki, kozmetičarke in pripadniki podobnih poklicev smejo imeti telesni stik le tako daleč, dokler ostaja »brez odnosa«. Ortoped, ki bi svojega pacienta po preiskavi pobožal po hrbtu, bi pacienta prav gotovo zmedel.</p>
<p>V naši kulturi smo podvrženi močnim omejitvam telesnega stika in ustreznim blokadam. Čeprav bi bilo treba obžalovati to odtujenost, moramo računati na to pri naših klientih. Telesni stiki so stiki bližine, ustvarjajo intimnost. Ustrezni so samo, če in dokler ta bližina ustreza odnosu med klientom in terapevtom, če to oba želita.</p>
<p>Vsi telesni stiki pomenijo tako priložnost kot tudi travmatizacijo terapevtskega odnosa. Zahtevajo posebno terapevtsko občutljivost.</p>
<p>Mnogi klienti, posebej s hudimi prizadetostmi, trpijo zaradi zgodovine telesnih nedopustnih posegov in mejnih poškodb, ki so delno nasilne in / ali seksualne narave. Ti klienti so lahko prizadeti ali prestrašeni zaradi »naivnega« (napačen trenutek, napačen način) telesnega stika terapevta. Včasih morajo celo svoj strah razcepljeno izraziti v obliki telesne otrplosti, da tako ne postavijo na kocko terapevtskega odnosa. Včasih pa lahko takšna »strokovna napaka« deluje tudi pozitivno, da terapevt uvidi telesno otrplost zaradi »prezgodnjega« dotika in tako lahko nagovori zasute, odcepljene klientove občutke ter tako dolgoročno omogoči terapevtsko delo na njih.</p>
<p>Vsekakor je priporočljivo natančno zaznavati in klienta rajši enkrat več kot enkrat premalo vprašati, ali mu dotik ugaja in ali mu tako ugaja!</p>
<p>Posledice nepredelanega »transferja terapevta« so na področju telesnega stika posebej usodne, kadar terapevt iz lastnih potreb po telesni bližini (»resnični stiki so samo telesni«) ali iz svoje narcistične potrebe (»Jaz sem vendar najboljši oče/ terapevt«) vsiljuje svojo bližino ali če telesno bližino ne da bi opazil napravi za cilj terapije.</p>
<p>Tudi transfer klienta je lahko prav na telesnem področju posebej težak: kadar klient ne more razlikovati svoje intenzivne želje po bližini in varnosti od želje po seksualnem stiku, pri telesnih stikih ne bo prišlo do pomiritve, temveč do vzburjenosti ali otrplosti, podobno temu, kar je klient verjetno doživljal v svoji osebni zgodovini.</p>
<p>Pri terapevtskem delu s telesnim kontaktom se gibljemo po ostrini noža: odločna odklonitev bo klienta vrgla nazaj, še tako previdno nagovarjanje seksualiziranih želja pa bo njega in terapevtski odnos še bolj zmedlo.</p>
<p>Psihoterapevt mora tukaj zelo natančno zaznavati svoj lastni mir ali vznemirjenost, da najde primeren stik.</p>
<h3 class="section-title">GIBALNA INTEGRATIVNA TERAPIJA</h3>
<p>Kakršnekoli motnje v človekovem zdravju, ne glede na to, kakšne vrste so ali kako so nastale, težijo k dezintegraciji človeka. Motnja se vedno odslikava v delovanju na celoto, zato mora tudi terapija biti usmerjena na človeka kot celoto, pri čemer lahko upamo, da bodo pozitivne spremembe na eni ravni izzvale ozdravljenje celotnega organizma.</p>
<p>Pri utrjevanju terapevtskih ciljev je potrebno imeti v mislih zahtevo po visoki stopnji identitete in samoregulacije, v klasičnem antropološkem terminu torej visoko stopnjo avtonomije in svobode, in zahtevo po dobrih stikih z življenjskim svetom.</p>
<p>Če se med terapijo ugotovi pri klientu, da je premalo senzibilen, ekspresiven in fleksibilen ali celo mišično zakrčen, potem je jasno, da se ni sposoben sprostiti, prepustiti, zato z različnimi terapevtskimi vajami delamo z njim na tem, da bi dosegel senzibilnost in bil sposoben psihofizične sprostitve, ali pa delamo postopno desenzibilizacijo, trening samopotrjevanja.</p>
<p>Lahko mu predlagamo bimodalno terapijo (ples, dihalne vaje, taoistične vaje, energetske vaje, jogo, kultivirane vzhodnjaške borilne veščine kot aikido, tai chi, kung fu), torej opogumljamo klienta, da sam (zavestno, ustvarjalno in samoodgovorno), v organizirani skupini ali v bimodalni terapiji s terapevtom naredi nekaj zase, da eksperimentira in poskuša nove možnosti vedenja, kar skoraj po pravilu pripelje do tega, da so terapevtski cilji hitreje doseženi.</p>
<p>Temeljni cilj gibalno terapevtskega dela v IT je obujanje zavesti o telesu (naša lastna zgodovina nam je v določeni meri pisana na telo), samoregulacije in psihofizične sprostitve.</p>
<p>Psihofizični trening sproščanja pogosto deluje kot podlaga za osvobajanje napetosti, vendar ne moremo zaobiti ubesedene predelave problemov, ki so vzrok te napetosti. To pomeni, da je ponavadi nujno potrebno tudi psihoterapevtsko, na konflikte osredotočeno delo, ker se sicer globoko zakoreninjene zakrčenosti ne morejo trajno razrešiti. Samo globinska predelava, na primer, globlje ležečih anksioznih problemov ali zavrte agresivnosti, lahko omogoči, da se psihični mehanizmi, ki peljejo k somatizaciji, onemogočijo in da tako pride do dolgotrajne spremembe, preobrazbe.</p>
<p>Pri tem lahko torej uporabimo sprostitveni trening kot suportivni in razreševalni moment. Obenem pa je potrebno seveda delati tudi na globlje ležeči problematiki.</p>
<h3 class="section-title">PRIPOVEDOVANJE ZGODB V IT</h3>
<p>Zgodba, legenda, pripovedka je v psihoterapiji namenjena temu, da obogati človekovo življenje, mu pomaga, da si pojasnjuje svoja čustva, da razvija svojo modrost in poišče življenjski smisel.</p>
<p>Zgodba mora biti uglašena z njegovimi strahovi, notranjimi konflikti in prizadevanji; priznavati mora njegove težave in hkrati nakazovati rešitve problemov, ki ga mučijo. Večina zgodb govori o dobrem in zlu, ki imata oba(!) svoje čare.</p>
<p>Preden se terapevt odloči za zgodbo, se mora s klientom uglasiti ter zgodbo opremiti s podobami (plastični način pripovedovanja), ki v klientu sprožijo odziv.</p>
<p>Višja logika(!) ustvari povezavo med stvarnostjo in domišljijo ter razkrije, kako lahko dva svetova prideta skupaj: bodisi tako, da ju združimo v sami zgodbi, ali pa tako, da zgradimo most med svetom v zgodbi in stvarnim svetom klienta.</p>
<h3 class="section-title">POJEM VLOGE IN PRIZORA (SCENE) V IT</h3>
<p>Integrativna terapija se manifestira tudi v psihodramski tradiciji (Moreno).</p>
<p>Naše življenje in vedenje si lahko poenostavljeno predstavljamo kot igro na odru. Pojem vloge združuje »zunanje«, to je socialno pričakovanje, in »notranje«, to je individualno predstavo ter presega ločitev med obema, saj vloge človek uteleša (na primer, kot učiteljica moram ustrezati določenim pričakovanjem glede znanja, prilagodljivosti, odprtosti in kontaktne sposobnosti, toda v osebni spontanosti in kreativnosti, ki ga spodbuja tudi psihodrama, pa imam znaten »manevrski prostor«).</p>
<p>V IT je posebno pomembno ukvarjati se s tem, do katere meje se klient počuti kot glavni igralec, ali je sploh avtor svojega življenja in v kolikšni meri to je ali bi lahko bil. Koliko razvojnih možnosti, kolikšno lastno odgovornost in iniciativo ter perspektivo prihodnosti ima ali bi jo lahko imel? Kako zelo se doživlja kot »gonilo nagonov« ali »kapitan brez ladje«?</p>
<p>V IT pojem vloge nima pomena »napačno, slepilo, maskirano«, kot je pogosto v pogovornem jeziku, temveč vloge predstavljajo prvo orientacijo v dogajanju glede odnosa med osebami.</p>
<p>Če smuknemo v vlogo drugih, smuknemo v njihovo kožo; torej ne zajamemo le njihovih posameznih lastnosti. Identifikacijo lahko ponazorimo v igri vlog s praznim stolom. Lahko se identificiramo tudi z določenimi posamičnimi vidiki partnerja v odnosu, z njegovimi potrebami, z njegovim besom. Z identifikacijo lahko odnosne konflikte in notranje konflikte «preprosto« simbolično izrazimo in jih poskušamo razumeti v življenjskem kontekstu in zaporedju, da se jih lahko osvobodimo in prerastemo.</p>
<h3 class="section-title">TERAPEVTSKO (PSIHODRAMSKO) DELO S PRAVLJICO V IT</h3>
<p>V IT uporabljamo pravljico (pravljica je neposredni nosilec projekcije) tudi kot klinično gradivo v obliki psihodrame, kjer klient prevzame eno ali vse vloge in lahko predeluje svojo »dramo« s pomočjo »praznega stola« z identifikacijo na ravni fantazije. Gre za dramatiziranje psihičnih konfliktov tu in sedaj. V človeku se lahko katarzično sprostijo zatrti in izrinjeni afekti. V psihodrami lahko storimo to, česar sicer v realnosti nimamo poguma storiti.</p>
<p>Življenjska situacija in situacija v pravljici<br>
Zelo pomembno vlogo pri vpeljavi psihodrame odigra ogrevanje, ki je potrebno za razgradnjo strahu, zgraditev zaupanja tako da se klient sploh odloči, ali bo predstavil svoje probleme. Ogrevanje pa rabi tudi za to, da se pri klientu vzbudijo čustva. Gre za to, da se poiščejo k tem čustvom ustrezne situacije, in s tem se začne lastna psihodrama.</p>
<p>Pogosto je dani prizor le predhodnik lastne drame kolikor se med »igranjem« klientu »odpre«, da prav to situacijo, ki jo doživlja s sedanjim partnerjem, že pozna iz svojega odnosa: oče-mati-brati-sestre. V takem primeru se potem »na novo« zgradi prizor in se ponovno preživi nekončana situacija iz preteklosti.</p>
<p>Psihodrama v IT pa daje tudi možnost poiskati alternativne rešitve in jih preizkusiti v terapevtski igri vlog.</p>
<p>K tehnikam psihodrame v IT sodi tudi menjavanje vlog in podvojitev oziroma pomožni Jaz, to pomeni, da terapevt ali član skupine, kadar gre za skupinsko obliko terapije, izgovarja neizgovorjene misli in občutke glavnega igralca. Pri tem stoji za njim ali ob njem.</p>
<p>To je lahko tudi neustrezno, nevarno v primeru, če to doteka v klienta kot tuj material(!).</p>
<p>Če pravljico psihodramsko obdelamo, lahko ugotovimo, da tudi tu pride do veljave pozabljeno ali izrinjeno, kar se potem v prizoru na novo predela. Namesto prizora iz pravljice stopi v prostor scena klienta iz preteklosti (ali iz sedanjosti). Prav tako dobro pa lahko učinkuje doživljanje pravljice same v obliki , ki jo da klient, zaključevanje nekončane situacije.</p>
<p>Dobiček za klienta je v tem, da izkusi, kje sedaj stoji. Od tod naprej lahko gre v smeri, ki ustreza njemu. Od tod lahko raste. Sprememba se dogodi potem, ko nekdo postane to, kar je, in ne, če poskuša postati to, kar ni. Od tod lahko doživi svoje možnosti lahko so popolnoma drugačne kot v tradicionalni obdelavi pravljic.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">Lastno oblikovanje in tradicionalna oblika pravljice</h4>
<p>V IT nam ne gre za to, da bi trdne oblike pravljice obdržali. Ne gre za zvesto ponovitev pravljice, temveč za to, kako klient sedaj zazna osebo in njeno usodo spelje do konca. Zato lahko kliente tudi spodbudimo, da pravljico od tam, kjer so jo začutili, do konca dosanjajo, doživijo ali napišejo tako, kot njim ustreza.</p>
<p>Vse to pa ne izključuje možnosti, da ne bi kdaj, kadar je potrebno, kliente soočili s tradicionalno formo. To lahko pelje k temu, da klient zazna, kako enostransko, nepopolno ali manipulativno se vede!</p>
<h3 class="section-title">POMEN GLASBENE TERAPIJE V IT</h3>
<p>Sodobna družba gleda na glasbo na dva načina: kot na umetnost in kot na reklamni izdelek. Potrebno je, da glasbo, glas in zvok pogledamo še z enega vidika, namreč, kot moč univerzalne energije. To energijo so v starih civilizacijah zelo spoštovali. Fizični zvok je bil zanje zunanji, slišni učinek notranje preobrazbe.</p>
<p>Kako torej nevidna moč zvoka deluje na nas?<br>
Glasba je strukturirana resničnost, saj jo lahko ne le slišimo, temveč tudi občutimo s celim telesom, in kot taka ima močan terapevtski učinek. Vibracije zvoka lahko spremenijo vzorce naših možganskih valovanj v stanje globoke psihofizične sprostitve ali pa ti vzorci prerastejo v ustvarjalno svobodo in intuitivni navdih.</p>
<p>Glasbeni terapevti pravijo, da ne more obstajati enotna glasbena »apoteka«, saj ista glasba lahko vzbudi različna čustva pri različnih ljudeh, saj ima vsak človek individualne občutke zaradi različne socializacije v glasbi in različne osebne izkušnje.</p>
<p>Obstaja pa neke vrste nevarnost za glasbene terapevte, če menijo, da imajo pred seboj medij, ki je univerzalen (»saj ga lahko vsi govorijo in razumejo«); a v terapevtskem odnosu pogosto vidimo, da ga vsi ne razumejo enako, zato je potrebno o tem spregovoriti še v feedbacku, še posebej, kadar gre za pomembno temo. Če pa je namen glasbe le sprostitev in uživanje, potem pogovor kasneje ni potreben.</p>
<p>Glasba združuje ljudi. To je tudi polje projekcij.</p>
<p>Denimo, glasbeni terapevt pogosto igra skupaj s klienti. Kot terapevt je lahko involviran s svojimi občutki v glasbi, kajti glasbeno dogajanje spodbuja občutke, ki bi lahko bili tudi projekcija: na primer, če je prijetna glasba - torej zbližajoči zvoki - imata morda oba, terapevt in klient, dobro izkušnjo, in to lahko pelje k stanju, ki pomeni: » razumela sva se«, pa čeprav v resnici za to ni podlage.</p>
<p>Težava je tudi v tem, da včasih ne najdemo besed ob glasbi, ki jo doživljamo; zato je pomembno, da iščemo pravilne besede, ne le ostanemo pri tem, da je to »lepa glasba«. Pomembna je torej diferenciacija občutkov, percepcij.</p>
<p>Prednost glasbe pa je v tem, da je brez besed. Lahko torej najdemo ozračja, razpoloženja in stanja iz zgodnjih faz razvoja, torej lahko skozi glasbo pridemo v stik s preverbalnim stadijem razvoja. To pomeni, da lahko sporočamo (komuniciramo) neke zgodnje situacije iz svojega življenja, za katere še ne najdemo besed.</p>
<p>In morda preko izkušnje z glasbenim sporočanjem najdemo te besede kot odrasla oseba.</p>
<p>Primeri:<br>
Izbira instrumenta v delu s pari je izredno pomembna. Dominantni partner ponavadi izbere po jakosti močnejši instrument, drugi pa nekaj tihega, zato jima terapevt pozneje po takšnem glasbenem dialogu naroči, naj sedaj zamenjata instrumente.<br>
Če želim za klienta igrati podpirajočo glasbo, in on, denimo, izbere flavto, vzamem jaz kot terapevt nekaj, kar to podpira, in če ne najdem začetne glasbe, mu dam » potujočo preprogo«.<br>
Če nekdo igra le monotono, ga poskusim » sprovocirati« z nečim zelo različnim od tega, kar on igra, to je lahko provokacija in/ali pa tudi spodbuda zanj, da bo iskal nove perspektive zase.</p>
<p>Če terapevt nenadoma neha igrati, lahko opazuje, kaj bo naredil klient, na primer, ali bo dovolj močan, da bo nadaljeval z igranjem, ali pa še vedno potrebuje spodbudo s strani terapevta (z njegovim igranjem).</p>
<p>Glasba je ogledalo dveh ali več ljudi, ki igrajo skupaj, odnosa v igranju, in ogledalo, kaj se dogaja v skupini, na primer, kje je razporejena moč.</p>
<p>V glasbeni terapiji IT obstaja tudi možnost zamenjave vlog (zdravilna pomoč), ko se terapevt preko glasbe postavi najprej v neko drugo vlogo in šele nato nadaljuje pogovorno terapijo v smislu IT.</p>
<p>Glasba je resnični medij most med ljudmi in - tudi varstvo, saj ni potrebno iti takoj neposredno v stik, ker imamo vmes določen instrument.</p>
<p>Učinkoviti terapevtski dejavniki v glasbi:</p>
<ul>
<li>čustvovanje,</li>
<li>empatija,</li>
<li>čustvena podpora,</li>
<li>svetovanje v kriznih življenjskih okoliščinah,</li>
<li>spodbujanje uvida,</li>
<li>spodbujanje sposobnosti za odnos (komunikacija),</li>
<li>možnosti za učenje,</li>
<li>spreminjanje tonusa telesa (napetost se lahko zvišuje ali zmanjšuje),</li>
<li>izražanje kreativne svobode,</li>
<li>spodbujanje povezovanja v skupini, pri čemer pa se ne izgubi identiteta posameznika.</li>
</ul>
<h3 class="section-title">NAMESTO SKLEPA</h3>
<p>Vsi ti terapevtski pristopi in intervencije v IT označujejo povezavo z antropologijo ustvarjalnega človeka.</p>
<p>Na temelju večperspektivnega razvoja klienti v IT prakticirajo stil psihoterapevtske obravnave, ki aktivira lastno izkušnjo, v kateri je proces odkrivanja in predelave moč kombinirati s tehnikami podpore in opogumljanja ter aktivne orientacije.</p>
<h4 style="font-family: var(--font-heading); margin-top: var(--spacing-l);">VIRI</h4>
<ul>
<li>1. Petzold, H. G. (1996). Krankheitsursachen im Erwachsenenleben Perspektiven fur diagnostik, Therapie und Lebeshilfe aus integrativertherapeutischer Saicht. Integrative Therapie, 2-3, Junfermann Verlag.</li>
<li>2. Petzold, H. G. (1994a). Kreative Personlischkeitsdiagnostik durch "mediengestutzte Technicken" in der Integrativen Therapie und Beratung. Integrative Therapie, 4, Junfermann Verlag (prevod v slovenščini kot interna skripta).</li>
<li>3. Bosse, S., Otte, H:, Rahm, D. (1997). Uvod v Integrativno terapijo (interna skripta). Slovenski prevod dela istoimenskih avtorjev: Einführung in die Integrative Therapie.</li>
</ul>
<p>(Mednarodni kongres psihoterapevtov Slovenije, Radenci 2005)</p>
</article>
<!-- === DODATNA POVEZAVA ZA NA VRH (DODANO) === -->
<div class="content-cta animate-on-scroll">
<a href="#">Na vrh ↑</a>
</div>
</section>
<!-- === GUMB ZA NA VRH (DODANO) === -->
<a href="#" id="back-to-top-btn" class="back-to-top-btn" aria-label="Na vrh strani">↑</a>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<!-- JavaScript -->
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./blog/psihoterapija-z-ozavescenim-psihoterapevtom/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Psihoterapija z ozaveščenim psihoterapevtom | Blog</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="container">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<div class="article-hero-image animate-on-scroll" style="background-image: url('https://placehold.co/1200x500/5E6472/FFFFFF?text=Razvoj');"></div>
<article class="article-content">
<p class="animate-on-scroll">Že Bruce Lee je govoril, da če želimo biti srečni in uspešni, je pravilo št. 1: najprej spoznaj samega sebe, preden spoznaš svet. In bodi hraber. kajti če ne spoznaš samega sebe, te bo kdo drugi z lahkoto naredil takšnega kot on hoče, da ti si.</p>
<p class="animate-on-scroll">A sprejeti je potrebno lastno odgovornost, ne pa ostajati pasiven, lenoben, ali ostajati v »coni komforta«. imej hrabrost, da se začutiš, da se spoznaš in stopaš na pot sprememb. Ko se spoznavaš, se začneš spreminjati od znotraj, spreminjaš pa tudi svoje vedenje, saj si dojel nekatere impulze, ki ti ne služijo več. in tako dejansko ozaveščaš svoje življenje in pristne danosti avtentične darove, ki so v tebi, a tega ne živiš.</p>
<p class="animate-on-scroll">V psihoterapiji z ozaveščenim psihoterapevtom skozi delo na sebi in opazovanje samega sebe in svoje osebnosti, imaš možnost spoznavanja samega sebe. In v tem tvojem procesu prebujanja, spoznavanja samega sebe in zato svojega nenehnega razvijanja od znotraj navzven, ti je ozaveščen psihoterapevt lahko v resnično empatično podporo in pomoč.</p>
<p class="animate-on-scroll">Daj, opogumi se in naredi prvi korak k odločitvi za psihoterapijo - da se premakneš z mesta, kjer si zdaj. Nato naredi naslednji korak. in potem še naslednjega, in stopaj naprej...vedno naprej! na poti tvojega življenja.</p>
<h3 class="animate-on-scroll">Psihoterapija z ozaveščenim psihoterapevtom - nenehno poteka v smeri človekovega neskončnega razvoja.</h3>
<p class="animate-on-scroll">Ljudje smo kompleksni, hkrati živimo in funkcioniramo na mnogih nivojih. zato se v psihoterapiji človeka tako tudi obravnava. Vloga ozaveščenega psihoterapevta je podpreti klienta, da je pripravljen z večjim zaupanjem kot do sedaj spoznati sebe in ugotoviti, na katerem nivoju je vzrok za njegovo stanje neravnotežja v življenju, pa naj gre za določeno energijsko blokado, duševne stiske, boleča čustva, boleče spomine, napornih stresnih situacij, občutke ogroženosti zaradi neugodnega zdravstvenega počutja in/ali nerešenih travm oddaljene ali nedavne preteklosti, kar vse pogosto direktno vibrira na sedanje podaljšano zdravstveno in duševno stisko človeka.</p>
<p class="animate-on-scroll">In če delujete v psihoterapevtskem procesu dela na sebi z večjim zavedanjem iz srca, in z zaupanjem ter s hrabrostjo odpirati, prevetriti poti, po katerih potujete, vam vaša duša, pravzaprav pa kar vaša celovita osebnost nenehno odstirata »sence« na vaših življenjskih poteh, kar vas seveda pripelje v notranjo transformacijo, in v razreševanje k rešitvi vaših konkretnih težav, stisk, problemov, nalog, ciljev.</p>
<p class="animate-on-scroll">Kot ozaveščen psihoterapevt vam želim tudi povedati, da smo vsi nenehno v procesu učenja in razvoja, ki ga jaz imenujem - naš večni razvoj. In vedite: jaz vas ne učim ničesar! Samo pomagam vam, da izrazite sami sebe! Da boste resnično sijali navzven, zasijte od znotraj...</p>
</article>
<div class="content-cta animate-on-scroll">
<a href="/blog/" class="back-to-blog">← Nazaj na vse članke</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./blog/soocanje-z-notranjimi-obcutki/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Soočanje z notranjimi občutki | Blog</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="container">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<div class="article-hero-image animate-on-scroll" style="background-image: url('https://placehold.co/1200x500/5C8374/FFFFFF?text=Soočanje');"></div>
<article class="article-content">
<p class="animate-on-scroll">Težko je strpati vse svoje želje, razmišljanja, hrepenenja, strahove v tako omejeni prostor kot je telo. Zakaj smo stalno napeti, nemirni in se počutimo prikrajšani, izčrpani, prenatrpani, zablokirani, v zatečenem stanju? Ni nujno, da se vsega tega tudi zavedamo, a zagotovo vsakdo občuti, da nekaj ni v redu. Vsako telo ima v sebi zapisane vse svoje zgodbe in jih pripoveduje na svoj lasten način (v obliki bolečine, izčrpanosti, otopelosti, poškodbe, bolezni).</p>
<p class="animate-on-scroll">Potrebno je razumeti, da je delitev na telo in um absolutno napačna. Če ločite sebe od svojega telesa, to vodi v potlačitev. Čim bolj tlačite telo, tem bolj boste razočarani, kajti potlačitev na daljši rok ni mogoča. Možno je doseči trenutno premirje, ampak potem boste spet poraženi.</p>
<p class="animate-on-scroll">Psihoterapija je zdravilo, ki zdravi razklanost telesa in duše. Psihoterapevti imamo isti namen dvigniti ljudi k zrelosti in preobrazbi, a poti in tehnike za to so različne.</p>
</article>
<div class="content-cta animate-on-scroll">
<a href="/blog/" class="back-to-blog">← Nazaj na vse članke</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./blog/stres-je-upiranje-spremembam/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stres je upiranje spremembam | Blog</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="container">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<div class="article-hero-image animate-on-scroll" style="background-image: url('https://placehold.co/1200x500/888C9B/FFFFFF?text=Spremembe');"></div>
<article class="article-content">
<p class="animate-on-scroll">Če postajajo nemir, napetost, utrujenost, brezvoljnost in pomanjkanje radosti stalni spremljevalci našega življenja, je čas, da se zaustavimo in poiščemo globlji stik s seboj. Kljub hitremu, frenetičnemu vrvenju življenja okoli nas, namreč ni treba, da podležemo stresu. »Stres je v osnovi odpor proti spremembam. Ko se stvari spreminjajo, mi pa ne želimo narediti spremembe pri sebi, ki je potrebna, bomo izkušali stres tako dolgo, dokler se bomo upirali spremembi. V življenju pa moramo biti pogumni, ni nam potrebno čakati na prebuditev do starosti. Biti moramo zelo živi in igrivi, kar pomeni tudi tvegati, da bomo morda prepoznali in občutili stvari, dogodke, spomine, ki jih ne želimo, in za katere smo mislili, da jih nikoli ne bomo čutili,« pravi Hermina Merc, magistrica klinična psihologinja specialistka in psihoterapevtka z evropsko diplomo ter supervizorka Evropske akademije za psihosocialno zdravje in razvijanje ustvarjalnosti iz Nemčije (EAG Fritz Perls Institut).</p>
<p class="animate-on-scroll">Sodobno življenje, ki ga vodi diktat iskanja užitkov in pretirane dejavnosti ter s tem samoizčrpavanja, terja svoj davek: čedalje več ljudi pestijo psihosomatske bolezni, ki na daljši rok vodijo v izgorelost. Ljudje se s stresom spoprijemajo na različne načine.</p>
<p class="animate-on-scroll">Sodobna družba od ljudi pričakuje, da bodo zmogli hitreje misliti, več delati, se odlikovati v vsem, česar se lotijo. Tudi naša pričakovanja do sebe so vedno večja, tako da postaja vzrok za stres pravzaprav vse, česar se lotimo. Nekateri pravijo, da lažje delajo pod »pritiskom«. Če se naprezamo v okviru svojih zmožnosti, bomo morda uspešni, če pa se naprezamo izven tega okvira, se bomo znašli pod fizičnim in/ali psihičnim pritiskom.</p>
</article>
<div class="content-cta animate-on-scroll">
<a href="/blog/" class="back-to-blog">← Nazaj na vse članke</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./blog/zivljenje-ki-inspirira/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Življenje, ki inspirira | Blog</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="container">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<div class="article-hero-image animate-on-scroll" style="background-image: url('https://placehold.co/1200x500/C08497/FFFFFF?text=Inspiracija');"></div>
<article class="article-content">
<p class="animate-on-scroll">Verjetno se strinjate, da življenje vsakogar testira, a četudi boste nerazumljeni, bodite neustavljivi, in nikoli ne odnehajte. bodite hrabri. Psihoterapija pomeni poglobljeno psihološko delo na sebi in spoznavanje sebe skozi celostno usmerjeno psihoterapijo, in to pomeni, da začnete živeti tako, da druge inspirirate, ne pa impresionirate.</p>
</article>
<div class="content-cta animate-on-scroll">
<a href="/blog/" class="back-to-blog">← Nazaj na vse članke</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./cenik/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cenik storitev | Mag. Hermina Merc</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<!-- CSS Stylesheet -->
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content cenik-page-main-content">
<section class="page-hero cenik-page-hero">
<div class="container">
<!-- Zunanji vsebnik za pozicioniranje slike -->
<div class="cenik-hero-image-wrapper animate-on-scroll">
<!-- Notranji vsebnik, ki ustvari kvadratno razmerje -->
<div class="cenik-hero-image-container">
<img src="/assets/images/tempelj.webp" alt="Tempelj v naravi">
</div>
</div>
<!-- Besedilo na desni strani -->
<div class="cenik-hero-text-content animate-on-scroll">
<h1 class="page-title">Cenik storitev</h1>
<p class="page-subtitle">Pregleden in transparenten vpogled v cene mojih storitev. Za vse dodatne informacije sem vam na voljo preko kontaktnega obrazca.</p>
</div>
</div>
</section>
<section class="container">
<div class="pricing-accordion">
<!-- Kategorija: Posvet -->
<div class="accordion-item animate-on-scroll">
<button class="accordion-header">
Posvet
<span class="accordion-icon"></span>
</button>
<div class="accordion-content">
<ul class="price-list">
<li class="price-item"><span class="service-name">Posvet</span><span class="service-price">150 €/90 min</span></li>
<li class="price-item"><span class="service-name">Posvet, nujni (do 7 dni)</span><span class="service-price">220 €/90 min</span></li>
<li class="price-item"><span class="service-name">Posvet, 2 osebi</span><span class="service-price">250 €/90 min</span></li>
</ul>
</div>
</div>
<!-- Kategorija: Psihoterapija -->
<div class="accordion-item animate-on-scroll">
<button class="accordion-header">
Psihoterapija
<span class="accordion-icon"></span>
</button>
<div class="accordion-content">
<ul class="price-list">
<li class="price-item"><span class="service-name">Psihoterapija, integralna individualna</span><span class="service-price">100 €/h</span></li>
<li class="price-item"><span class="service-name">Psihoterapija, integralna individualna/prednostna</span><span class="service-price">150 €/h</span></li>
<li class="price-item"><span class="service-name">Psihoterapija integralna za ljudi profesionalnih poklicev (Managerji, poslovneži, vodilni kadri, medicina, psihologija, izobraževanje, sociala, ipd.)</span><span class="service-price">120 €/h</span></li>
<li class="price-item"><span class="service-name">Psihoterapija, integralna/ 2 osebi (partnerska, družinska)</span><span class="service-price">220 €/h</span></li>
<li class="price-item"><span class="service-name">Psihoterapija, integralna skupinska/po osebi</span><span class="service-price">80 €/h</span></li>
<li class="price-item"><span class="service-name">Učna izkustvena psihoterapevtska analiza /individualna (90 min.)</span><span class="service-price">180 €</span></li>
</ul>
</div>
</div>
<!-- Kategorija: Supervizija -->
<div class="accordion-item animate-on-scroll">
<button class="accordion-header">
Supervizija / Profesionalno svetovanje
<span class="accordion-icon"></span>
</button>
<div class="accordion-content">
<ul class="price-list">
<li class="price-item"><span class="service-name">Supervizija/psihoterapevtstvo profesionalno svetovanje/individualna</span><span class="service-price">150 €/h</span></li>
<li class="price-item"><span class="service-name">Supervizija/psihoterapevtstvo profesionalno svetovanje/skupinska/po osebi</span><span class="service-price">100 €/h</span></li>
</ul>
</div>
</div>
<!-- Kategorija: Psihofizična Sprostitev -->
<div class="accordion-item animate-on-scroll">
<button class="accordion-header">
Psihofizična / Psihoterapevtska sprostitev
<span class="accordion-icon"></span>
</button>
<div class="accordion-content">
<ul class="price-list">
<li class="price-item"><span class="service-name">Psihofizična psihološka protistresna sprostitev/individualna</span><span class="service-price">120 €/h</span></li>
<li class="price-item"><span class="service-name">Psihofizična psihološka protistresna sprostitev/skupinska/po osebi</span><span class="service-price">50 €/h</span></li>
<li class="price-item"><span class="service-name">Psihofizična psihoterapevtska bimodalna sprostitev kot program srečanj v ciklusu /individualna</span><span class="service-price">150 €/h</span></li>
<li class="price-item"><span class="service-name">Psihofizična psihoterapevtska bimodalna sprostitev kot program srečanj v ciklusu/ skupinska/po osebi</span><span class="service-price">70 €/h</span></li>
</ul>
</div>
</div>
<!-- Kategorija: Zvočna Terapija -->
<div class="accordion-item animate-on-scroll">
<button class="accordion-header">
Zvočna terapevtska sprostitev z Gong glasbili
<span class="accordion-icon"></span>
</button>
<div class="accordion-content">
<ul class="price-list">
<li class="price-item"><span class="service-name">Individualna</span><span class="service-price">120 €/h</span></li>
<li class="price-item"><span class="service-name">Skupinska/po osebi</span><span class="service-price">60 €/h</span></li>
</ul>
</div>
</div>
<!-- Kategorija: Klinično-psihološke storitve -->
<div class="accordion-item animate-on-scroll">
<button class="accordion-header">
Klinično-psihološke specialistične storitve
<span class="accordion-icon"></span>
</button>
<div class="accordion-content">
<ul class="price-list">
<li class="price-item"><span class="service-name">Klin. psihološki specialistični pregled za procesne postopke (v šolskem izobraževanju, v poklicu, v zdravstvu, sociali, sodstvu, ipd.)</span><span class="service-price">420 €</span></li>
<li class="price-item"><span class="service-name">Strokovno specialistično klinično psihološko pisno poročilo in mnenje za procesne postopke (v šolskem izobraževanju, v poklicu, v zdravstvu, sociali, sodstvu, ipd.)</span><span class="service-price">420 €</span></li>
</ul>
</div>
</div>
</div>
<!-- Opomba s črtkanim okvirjem -->
<div class="special-pricing-note animate-on-scroll">
<h3>Predavanja, tematske delavnice, seminarji, pogovorna srečanja</h3>
<p>Cena po dogovoru</p>
</div>
<!-- Gumb za kontakt -->
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<!-- JavaScript -->
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Psihoterapevt, vrhunski strokovnjak | Mag. Hermina Merc</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<!-- Povezava na novo, glavno CSS datoteko -->
<link rel="stylesheet" href="assets/css/main.css" />
</head>
<body class="homepage">
<!-- ========================= HEADER ========================= -->
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<!-- ========================= SLIDER ========================= -->
<main id="slider" class="slider">
<!-- ──────────────── 1 ──────────────── -->
<section class="slide active">
<div class="slide-content">
<figure class="slide-image">
<img
src="/assets/images/home-slider-01-morje.webp"
alt="Morje s skalo v ozadju"
/>
</figure>
<div class="slide-text">
<!-- === PORTRET === -->
<figure class="slide-portrait">
<img src="/assets/images/portret.webp" alt="Portret mag. Hermine Merc">
</figure>
<h2>PSIHOTERAPEVT, VRHUNSKI STROKOVNJAK</h2>
<!-- === SPREMEMBA: Dodan razred za stil besedila === -->
<p class="text-accent-uppercase">
<strong>
mag. Hermina Merc<br />
psihoterapevt in specialist klinični psiholog
</strong>
</p>
<p>
<strong>
Kot vrhunski strokovnjak psihoterapevt in specialist klinični
psiholog sem vam zagotovo lahko v najboljšo strokovno pomoč pri
razreševanju vseh vaših raznolikih življenjskih situacij.
</strong>
</p>
</div>
</div>
</section>
<!-- ──────────────── 2 ──────────────── -->
<section class="slide">
<div class="slide-content">
<figure class="slide-image">
<img src="/assets/images/home-slider-02-palme.webp" alt="Pogled na palme in morje" />
</figure>
<div class="slide-text">
<h2>
Se soočate s stresom, tesnobo, nepredelanimi nikoli izpetimi stiskami in nalogami?
</h2>
<p>
Iščete globlje spoznavanje in empatično razumevanje sebe, ali pa si želite več radosti in harmonije v svojem življenju? Mag. Hermina Merc, priznana psihoterapevtka in specialistka klinične psihologije, vam ponuja strokovno podporo na vaših življenjskih poteh do boljšega počutja, razvijanja lastnega sebe, svoje celovite in avtentične osebnosti in svojih resničnih darov potencialov ter lastnih pristnih virov za harmonični tok zdravja in hkrati dinamičnega ravnovesja v življenju.
</p>
<p>
<strong>Zaupajte si in pogumno stopajte na pot psihoterapevtskega dela na sebi vsak korak naprej - vedno naprej je neprecenljiv potencial na vaši Poti Življenja!</strong>
</p>
</div>
</div>
</section>
<!-- ──────────────── 3 ──────────────── -->
<section class="slide">
<div class="slide-content">
<figure class="slide-image">
<img
src="/assets/images/home-slider-03-puscava.webp"
alt="Puščavska pokrajina"
/>
</figure>
<div class="slide-text">
<h2>Potovanje k samemu sebi</h2>
<p>
V tem naglem tempu življenja prepogosto pozabljamo, da je enako pomemben tudi naš notranji svet in naša najgloblja čustva. Kot ozaveščeni psihoterapevt vam lahko pomagam, da gremo skupaj na vaše potovanje znotraj sebe, da se najprej sploh soočite in s tem osvobodite bremen, blokad, ki jih nosite v telesu zablokirane - vede ali nevede že pre - dolgo.
</p>
<p>
Vedite, da te blokade niso trajne, ampak šele ko jih spoznate in prepoznate, kje v vašem telesu so »uspavane«, jih lahko razumete in jih sprostite iz sebe, s čimer osvobodite ne samo vaše telo teh bolečih blokad, temveč tudi vašo osebnost.
</p>
</div>
</div>
</section>
<!-- ──────────────── 4 ──────────────── -->
<section class="slide">
<div class="slide-content">
<figure class="slide-image">
<img
src="/assets/images/home-slider-04-kanjon-svetloba.webp"
alt="Svetloba, ki sije v kanjon"
/>
</figure>
<div class="slide-text">
<h2>Spoznajte lastni žarek zaupanja</h2>
<p class="large-text">
Z mojo strokovno podporo in pomočjo spoznajte lastni žarek zaupanja v svoje življenje, in zasijte od znotraj, da boste lahko zasijali tudi navzven.
</p>
</div>
</div>
</section>
<!-- ──────────────── 5 ──────────────── -->
<section class="slide">
<div class="slide-content">
<figure class="slide-image">
<img
src="/assets/images/home-slider-05-drevo-soteska.webp"
alt="Drevo, ki raste v soteski"
/>
</figure>
<div class="slide-text">
<h2>Starodavni modreci so poudarjali: Spoznajte samega sebe najprej, preden spoznaš svet.</h2>
<p>
In tudi jaz kot psihoterapevt vas želim spodbuditi, da lahko skozi psihoterapevtsko delo na sebi izjemno dobro spoznate lastne izvore za vaše zdravje in življenjsko harmonijo, skozi prepoznavanje in razvijanje svojih najbolj pristnih potencialov na svoji življenjski poti.
</p>
</div>
</div>
</section>
<!-- ──────────────── 6 ──────────────── -->
<section class="slide">
<div class="slide-content">
<figure class="slide-image">
<img
src="/assets/images/home-slider-06-rastlina-pesek.webp"
alt="Rastlina, ki raste iz peska"
/>
</figure>
<div class="slide-text">
<h2>Začutiti sebe, radost, energijo</h2>
<p>
Psihoterapija z menoj kot ozaveščenim psihoterapevtom vam v strokovnem smislu pomaga in vas podpre v vaši iskreni nameri: Priti ven iz samote in praznine in začutiti, da boleča teža ne pritiska več na vas in na vaše telo, temveč začutite, da je tukaj že radost, smeh iz srca, energija in dinamična harmonija, ki samo še čakajo, da jih prikličete k sebi.
</p>
</div>
</div>
</section>
<!-- ──────────────── 7 ──────────────── -->
<section class="slide">
<div class="slide-content">
<figure class="slide-image">
<img src="/assets/images/home-slider-07-papiga.webp" alt="Barvita papiga na veji" />
</figure>
<div class="slide-text">
<h2>Pristno začutiti sebe</h2>
<p>
Skozi pristno in resnično začutiti sebe v psihoterapevtskem procesu, se nenehno razvijate od znotraj navzven in tudi na zunaj. Poiščite v sebi takšno življenjsko energijo sebi v dobrobit in radost!
</p>
<p><strong>Vsekakor ste se rodili s potencialom in z darovi- spoznajte jih! In zaživite jih!</strong></p>
</div>
</div>
</section>
<!-- ──────────────── 8 ──────────────── -->
<section class="slide">
<div class="slide-content">
<figure class="slide-image">
<img src="/assets/images/home-slider-08-sipine.webp" alt="Peščene sipine" />
</figure>
<div class="slide-text">
<h2>Naredite prvi korak</h2>
<p class="large-text">
Na vas je, da naredite prvi konkreten korak pri razreševanju vseh vaših življenjskih situacij. Prijavite se na prvo srečanje pri meni kot vrhunskemu strokovnjaku psihoterapevtu, specialistu klinične psihologije!
</p>
<a href="kontakt/" class="cta">Naročite se na prvo srečanje</a>
</div>
</div>
</section>
</main>
<!-- navigacijski gumbi za slideshow -->
<button
id="prevBtn"
class="nav-btn prev"
aria-label="Prejšnji slide"
>
</button>
<button
id="nextBtn"
class="nav-btn next"
aria-label="Naslednji slide"
>
</button>
<!-- ========================= FOOTER ========================= -->
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<!-- Povezava na obstoječo JavaScript datoteko -->
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./kaj-je-psihoterapija/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kaj je psihoterapija | Mag. Hermina Merc</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<!-- CSS Stylesheet -->
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="container">
<h1 class="page-title animate-on-scroll">Kaj je psihoterapija?</h1>
<div class="image-grid">
<div class="grid-image animate-on-scroll" style="background-image: url('/assets/images/home-slider-05-drevo-soteska.webp');"></div>
<div class="grid-image animate-on-scroll" style="background-image: url('/assets/images/home-slider-04-kanjon-svetloba.webp');"></div>
</div>
<div class="text-section animate-on-scroll">
<!-- === POPRAVEK: Odstranjena vejica === -->
<h2 class="page-subtitle">Psihoterapija je subtilni proces spoznavanja samega sebe, ki spreminja ozavešča in osvobaja naš pogled na samega sebe.</h2>
</div>
<div class="text-section">
<div class="animate-on-scroll">
<p>Odkrivanje samega sebe in svojega življenjskega sveta, soočanje z življenjskimi strahovi in iluzijami v sedanjosti, preteklosti in prihodnosti odpira človeku v procesu psihoterapije vedno nove perspektive, do katerih mu pomaga psihoterapevt z različnimi psihoterapevtskimi znanji.</p>
<!-- === POPRAVEK: Dodan nov celoten tekst === -->
<p>Katere metode bodo izbrane pogosteje pa seveda pogojuje psihoterapevtova profesionalna kompetentnost, njegovo znanje in »terapevtsko orodje«, osebna angažiranost v psihoterapevtskem procesu, njegove profesionalne in življenjske izkušnje ter ne nazadnje njegova klinična modrost.</p>
<p>Človek bi moral v tem, kar ve o sebi, imeti na voljo spomine na otroštvo. Zato ni pomembno raziskovanje otroštva in zgodnje mladosti, pozabljenega, potisnjenega samo z vidika bolezni, da bi torej prišli do zavedanja o obremenjujočih in škodljivih vplivih, ki imajo za posledico motnje vedenja ali osebnostnega razvoja, temveč je raziskovanje samega sebe veliko bolj pomembno z vidika zdravja (energetsko ravnotežje), torej kot vedenja (zavedanja) o »dobrih izvorih« lastne biografije, ker to določa naš sedanji življenjski občutek.</p>
<p>Psihoterapija torej ne poudarja le zunanjega razvoja, temveč še bolj notranjega. Ker ta proces temelji na naravnih načelih zdravljenja, naj ne bi obstajala potreba po hitenju in težnji, da bi prišlo do spremembe čimprej. Vzeti si je potrebno dovolj časa, da začne človek razvijati občutek za samega sebe in postane bolj zavedajoč samega sebe. Če seveda človek nima nobenega kontakta s svojim notranjim svetom, potem se bo lastnih notranjih sprememb v začetnem procesu psihoterapije komaj kaj zavedal. Težko je namreč potovati skozi življenje s poškodovanimi instinkti in čuti, prav tako je težko iti skozi vse naše zunanje in notranje boje in osebno zgodovino našega življenja brez povezanosti z lastnim telesom, lastnim srcem, lastnim umom, lastno dušo.</p>
<p>Človek se v psihoterapiji lahko odpre svoji speči zmožnosti, da dovoli stvarem, dogodkom in ljudem, da obstajajo oziroma, da so se zgodile, brez sodb, brez vrednostnih ocenjevanj, saj bi sicer hranil proces odvisnosti od vzorcev preteklosti. Kajti v toku procesa psihoterapije se nam različne stvari (neprijetni spomini, travme, občutja) dvignejo iz podzavesti, in naše celovito zdravje, osebnostni in duhovni razvoj se dotika tega, da bomo postali nevtralni do teh dogodkov, ljudi ali stvari (se osvobodimo, prerastemo, preobrazimo).</p>
<p>Prav ta sprostitev od napetosti in osvoboditev od starih omejujočih vzorcev razmišljanja, vedenja in čustvovanja je pogoj za energijsko (telesno, čustveno, umsko in duhovno) samouravnoteženje. Če namreč hočemo v življenju in pri delu uživati, moramo vzdrževati visoko raven energije.</p>
</div>
</div>
<div class="text-section">
<h2 class="section-title animate-on-scroll">Kdaj in kako vstopiti v celostno psihoterapijo?</h2>
<blockquote class="highlight-quote animate-on-scroll">
<p>»Vsak človek nekoliko okleva, preden se potopi v globine (svojega življenja). Čeprav je vaše oklevanje naravno, ga je potrebno potisniti na stran, zbrati morate vsaj trenutek poguma, da skočite v mrzlo vodo, in vedite, da jo boste občutili kot resnično mrzlo samo za trenutek, že kmalu pa boste v sebi začutili svežino in novo živost.«</p>
<cite> Vzhodnjaški modrec</cite>
</blockquote>
<div class="animate-on-scroll">
<p>Rada bi vam povedala, da k meni kot integralnemu psihoterapevtu zatorej prihajate ljudje iz najrazličnejših potreb: lahko je to zgolj radovednost ali hudi čustveni pretresi v aktualnem življenju, razdražljivost (za mnoge ljudi razdraženost ali negativna čustva niso bolezen, čeprav v resnici že obstaja energetsko neravnotežje), lahko vas privede bolezen in njeni simptomi, ki govore, da sta telo in psiha nedeljiva celota, lahko pa so to vaša neizpolnjena hrepenenja, globlji občutek, da vašemu življenju manjka inspiracija za razvoj lastne avtentične osebne in duhovne razsežnosti.</p>
</div>
</div>
<div class="concluding-statement animate-on-scroll">
<!-- === POPRAVEK: Zamenjano celotno besedilo === -->
<p><strong>MNENJA SEM NAMREČ, DA BITI SAMO INTELIGENTEN IN OBČUTLJIV V ŽIVLJENJU NI DOVOLJ, POSTATI MORATE ODPRTI IN RANLJIVI, NOTRANJE IZPOLNJENI IN ZADOVOLJNI. IMETI MORATE TOLIKO POGUMA, DA RAZISKUJETE SAMEGA SEBE IN SVOJE ŽIVLJENJE TER GA V INTEGRALNEM PSIHOTERAPEVTSKEM PROCESU SPOZNATE PRISTNO, AVTENTIČNO, SAJ VAM RESNICE NE MOREJO DATI KNJIGE ALI NOVODOBNI SEMINARJI, KER SO NAMREČ PRAV VSI ODGOVORI NA VAŠA VPRAŠANJA ZNOTRAJ VAS SAMIH!</strong></p>
</div>
<div class="content-cta animate-on-scroll">
<!-- === POPRAVEK: Spremenjen tekst gumba === -->
<a href="/storitve/" class="cta-button">Predstavitev ponudbe</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<!-- JavaScript -->
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./kontakt/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kontakt in naročanje | Mag. Hermina Merc</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<!-- CSS Stylesheet -->
<link rel="stylesheet" href="/assets/css/main.css">
<!-- Stili za portret na kontaktni strani (ostanejo nespremenjeni) -->
<style>
.contact-portrait {
display: block;
width: 100%;
max-width: 250px;
height: auto;
margin: 0 auto var(--spacing-l) auto;
border-radius: 10px;
box-shadow: var(--shadow-medium);
}
</style>
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button class="mobile-nav-toggle" aria-controls="main-navigation" aria-expanded="false" aria-label="Toggle navigation">
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="page-hero">
<div class="container">
<h1 class="page-title animate-on-scroll">Kontaktirajte me</h1>
<p class="page-subtitle animate-on-scroll">Spoštovani obiskovalci moje spletne strani, vedite, da sem vam kot vrhunski strokovnjak lahko življenjsko v pomoč pri vseh vaših osebnih situacijah. Kontaktirajte me. Veselim se našega sodelovanja.</p>
</div>
</section>
<section class="container">
<div class="contact-grid">
<!-- Leva stran: Podatki in zemljevid -->
<div class="contact-details animate-on-scroll">
<h2 class="section-title">Informacije za naročanje</h2>
<img src="/assets/images/portret-2.webp" alt="Portret Hermina Merc" class="contact-portrait">
<div class="contact-info-item">
<p class="info-data"><strong>Mag. HERMINA MERC</strong><br>Psihoterapevt Specialist Klinični Psiholog</p>
</div>
<div class="contact-info-item">
<span class="info-label">Naslov:</span>
<p class="info-data">Krpanova ulica 19<br>2000 Maribor</p>
</div>
<div class="contact-info-item">
<span class="info-label">Elektronski naslov:</span>
<p class="info-data"><a href="mailto:info@herminamerc.si">info@herminamerc.si</a></p>
</div>
<div class="map-placeholder">
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2771.608350621415!2d15.63228067694923!3d46.55836895818817!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x476f76a8e8f8d689%3A0x6b1f9f2b36b281f9!2sKrpanova%20ulica%2019%2C%202000%20Maribor!5e0!3m2!1sen!2ssi" width="100%" height="100%" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
</div>
</div>
<!-- Desna stran: Kontaktni obrazec -->
<div class="contact-form-wrapper animate-on-scroll">
<h2 class="section-title">Pošljite sporočilo</h2>
<form id="contact-form" class="contact-form" novalidate>
<div class="form-group">
<label for="name">Ime in priimek</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">Vaš E-mail naslov</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="message">Kratko sporočilo</label>
<textarea id="message" name="message" rows="8" required maxlength="500"></textarea>
<div id="char-counter" class="char-counter">500 znakov na voljo</div>
</div>
<div class="form-group">
<!-- POPRAVEK: Gumbu je dodan razred "cta" za pravilen stil -->
<button type="submit" class="cta cta-button">Pošlji sporočilo</button>
</div>
</form>
<!-- Element za prikaz sporočil o uspehu/napaki, ki ga bo upravljal JavaScript -->
<div class="form-message" aria-live="polite"></div>
<p style="text-align: center; margin-top: 1rem; font-style: italic; font-size: 0.9rem;">Pri naročanju je potrebno termin predhodno dogovoriti po mailu.</p>
</div>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<!-- JavaScript -->
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./layouts/footer.html" :
"""
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>"""
"./layouts/header.html" :
"""
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>"""
"./navodila" :
"""
assets/
└── css/
├── base/
│ ├── _reset.css
│ ├── _variables.css
│ └── _typography.css
├── components/
│ ├── _accordion.css
│ ├── _buttons.css
│ ├── _cards.css
│ ├── _contact-form.css
│ ├── _header.css
│ ├── _footer.css
│ └── _slider.css
├── layout/
│ ├── _grids.css
│ └── _structure.css
├── pages/
│ └── _article.css
└── main.css
v celoti napiši datoteko main.css brez krajšanja ali poenostavljanja. napiši od začetka do konca in napiši vse stile/elemente, ki spadajo tja
"""
"./o-meni/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>O meni | Mag. Hermina Merc</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<!-- CSS Stylesheet -->
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage"> <!-- Dodan razred "subpage" za specifične stile -->
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="container">
<h1 class="page-title animate-on-scroll">O meni</h1>
<div class="about-grid">
<div class="about-image animate-on-scroll">
<img src="/assets/images/hermina-merc-portret.webp" alt="Fotografija Hermine Merc">
</div>
<div class="about-content">
<p class="intro-text animate-on-scroll">Kot psihoterapevtka delujem k ozaveščanju, kultiviranju in osmišljanju tako osebnostnega kot duhovnega potenciala posameznika.</p>
<div class="animate-on-scroll">
<p>Moje ime je Hermina Merc in sem magistrica psiholoških ved, specialistka klinična psihologinja in psihoterapevtka z evropsko diplomo (European Association for Psychotherapy EAP), terapevtka za osebno izkušnjo (učni terapevt) ter supervizorka Evropske akademije za psihosocialno zdravje in razvijanje kreativnosti iz Nemčije (EAG Fritz Perls Institut), z zasebno psihoterapevtsko prakso v Mariboru. Imam bogate strokovne izkušnje z različnimi psihoterapevtskimi usmeritvami (razvojno analitično integralno orientirana metoda zdravljenja, integrativna in geštaltistična).</p>
<p>Sem tudi certificirana učiteljica Kundalini joge (Kundalini Research Institute KRI) in Shakti dance Yoga plesa (avtorice SD Sare Avtar Olivier). Prav tako sem tudi cerificirana edukantka Nauka Grigorija Petrovicha Grabovoja že od začetka uradnega izobraževanja v Sloveniji od leta 2013 - 2014. Dr. Grigori Petrovich Grabovoi je eden najfascinantnejših postsovjetskih informacijskih duhovnih znanstvenih raziskovalcev človekovega Večnega Neskončnega razvoja skozi lastno ozaveščenost na Poteh življenja.</p>
</div>
<div class="animate-on-scroll">
<h2 class="section-title">Področja mojega aktivnega delovanja</h2>
<p>Področja mojega aktivnega delovanja so: integralna celostno usmerjena psihoterapija, psihoterapija za managerje in poslovneže, tematska predavanja, supervizija in učna analiza, namenjena za ljudi, ki v svoji profesiji delajo z drugimi ljudmi, športna psihologija, aktivne metode psihofizičnega sproščanja telesa in duha ter dihalne tehnike ozaveščenega dihanja v skupini ali individualno, bimodalna telesno orientirana psihoterapija, terapevtski sprostitveni ples, zvočna sprostitvena terapija z gong glasbili, poučevanje vadbe kundalini joge (individualno, skupinsko), ter razvijanje svoje pristne osebnosti skozi večje zavedanje na fizično telesnem in na duhovno informacijskem področju človekovega večnega neskončnega razvoja.</p>
</div>
<div class="animate-on-scroll">
<h2 class="section-title">Kaj lahko pričakujete od mene kot integralne psihoterapevtke in klinične psihologinje specialistke?</h2>
<p>Pričakujete lahko mojo polno profesionalno angažiranost in strokovno psihološko celovitost pri vodenju v vašem pristnem psihoterapevtskem delu na sebi, tako v spoznavanju, spoprijemanju in preraščanju osvobajanju psihosomatskih vzorcev stisk, težav, obolenj kot v dvigovanju v osebnostni rasti in duhovni preobrazbi.</p>
<p>Seveda ob predpostavki, da niste zgolj pasivni opazovalec v psihoterapevtskem procesu raziskovanja samega sebe in svojega življenja, temveč s pozornostjo, ljubeznijo, radostjo in odgovornostjo v smeri neizmerno več svobodne volje in polnega izražanja samega sebe in svojih pristnih življenjskih možnosti, potencialov, postanete aktivni ustvarjalec ustvarjalnih sprememb v vašem življenju.</p>
</div>
</div>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<!-- JavaScript -->
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./optimize_images.py" :
"""
import os
import argparse
import shutil
from PIL import Image
# --- Konfiguracija skripte za projekt "Hermina" ---
# Predpostavka: ta skripta se nahaja v korenski mapi projekta.
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
# Pot do mape, kjer se nahajajo slike, ki jih želimo optimizirati.
IMAGES_DIR_PATH = os.path.join("assets", "images")
# Ime podmape znotraj IMAGES_DIR_PATH, kamor se bodo shranile originalne slike.
ORIGINAL_IMAGES_SUBDIR_NAME = "original"
# Mape, ki jih želimo PREGLEDATI za posodobitev referenc na slike.
# '.' pomeni, da začnemo v korenski mapi in pregledamo vse podmape.
DIRECTORIES_TO_SCAN = ['.']
# Mape, ki jih želimo IZKLJUČITI iz pregledovanja (za hitrejše delovanje in varnost).
# Skripta ne bo iskala referenc v teh mapah.
DIRECTORIES_TO_EXCLUDE_FROM_SCAN = ['.git', '.gitea', '.vscode', '__pycache__']
# Končnice datotek, v katerih iščemo in posodabljamo reference na slike.
FILE_EXTENSIONS_TO_UPDATE = ['.html', '.css', '.js']
# Nastavitve optimizacije
WEBP_QUALITY = 85 # Kakovost kompresije za WebP (0-100). Višje = boljša kvaliteta, večja datoteka.
MAX_IMAGE_DIMENSION = 1920 # Slike, večje od te dimenzije (širina ali višina), bodo pomanjšane. 0 za izklop.
# Končnice slik, ki jih želimo optimizirati.
IMAGE_EXTENSIONS_TO_OPTIMIZE = ['.jpg', '.jpeg', '.png']
# Imena datotek, ki jih želimo preskočiti pri optimizaciji (npr. logotipi, ikone).
EXCLUDE_FILES_FROM_OPTIMIZATION = [
'favicon.ico'
# Dodajte imena drugih datotek po potrebi, npr. 'logo.png'
]
# --- Pomožne funkcije (večinoma nespremenjene) ---
def optimize_image(image_path, output_path, quality, max_dim, dry_run=False):
"""
Naloži sliko, jo po potrebi pomanjša, optimizira in pretvori v WebP format.
"""
try:
with Image.open(image_path) as img:
# Pretvorba slik s paleto (kot so nekatere PNG) v RGBA za ohranitev prosojnosti.
if img.mode in ('P', 'LA'):
img = img.convert("RGBA")
if max_dim > 0 and (img.width > max_dim or img.height > max_dim):
print(f" Pomanjšujem sliko {os.path.basename(image_path)} iz {img.width}x{img.height} ...", end="")
img.thumbnail((max_dim, max_dim), Image.Resampling.LANCZOS)
print(f" na {img.width}x{img.height}")
else:
print(f" Obdelujem sliko {os.path.basename(image_path)} ({img.width}x{img.height})...", end="")
if not dry_run:
img.save(output_path, "webp", quality=quality, method=6)
print(f" Shrani v {os.path.basename(output_path)} (kvaliteta: {quality}).")
else:
print(f" DRY RUN: Shranil bi v {os.path.basename(output_path)} (kvaliteta: {quality}).")
return True
except FileNotFoundError:
print(f" Napaka: Izvorna slika '{image_path}' ni najdena.")
return False
except Exception as e:
print(f" Napaka pri optimizaciji slike '{image_path}': {e}")
return False
def update_file_references(file_path, old_filename, new_filename, dry_run=False):
"""
V dani datoteki zamenja vse pojavitve starega imena slike z novim.
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
except Exception:
# Ignoriramo binarne ali neberljive datoteke
return False
if old_filename in content:
updated_content = content.replace(old_filename, new_filename)
if not dry_run:
try:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(updated_content)
print(f" Posodobljene reference v: '{os.path.relpath(file_path, PROJECT_ROOT)}'")
return True
except Exception as e:
print(f" Napaka pri zapisovanju v '{file_path}': {e}")
return False
else:
print(f" DRY RUN: Posodobil bi reference v: '{os.path.relpath(file_path, PROJECT_ROOT)}'")
return True
return False
def find_files_to_update(scan_dirs, exclude_dirs):
"""
Rekurzivno poišče vse datoteke z ustreznimi končnicami, pri tem pa ignorira izključene mape.
"""
found_files = []
for directory in scan_dirs:
scan_path = os.path.join(PROJECT_ROOT, directory)
for dirpath, dirnames, filenames in os.walk(scan_path):
# Učinkovit način za izključitev map: odstranimo jih iz seznama za nadaljnje pregledovanje
dirnames[:] = [d for d in dirnames if d not in exclude_dirs]
for filename in filenames:
if any(filename.endswith(ext) for ext in FILE_EXTENSIONS_TO_UPDATE):
found_files.append(os.path.join(dirpath, filename))
return sorted(list(set(found_files)))
# --- Glavna funkcija ---
def main():
parser = argparse.ArgumentParser(description="Optimizira slike v WebP in posodobi reference v projektu.")
parser.add_argument("--dry-run", action="store_true", help="Prikaže, katere spremembe bi se zgodile, a jih ne izvede.")
args = parser.parse_args()
images_full_path = os.path.join(PROJECT_ROOT, IMAGES_DIR_PATH)
original_images_full_path = os.path.join(images_full_path, ORIGINAL_IMAGES_SUBDIR_NAME)
# Dodamo mapo z originali v seznam za izključitev, da ne skeniramo še tam.
DIRECTORIES_TO_EXCLUDE_FROM_SCAN.append(ORIGINAL_IMAGES_SUBDIR_NAME)
if not os.path.isdir(images_full_path):
print(f"Napaka: Mapa s slikami '{images_full_path}' ne obstaja. Preverite pot v konfiguraciji.")
return
if not args.dry_run:
os.makedirs(original_images_full_path, exist_ok=True)
print(f"Mapa za originale: '{original_images_full_path}'")
else:
print(f"DRY RUN: Mapa za originale bi bila '{original_images_full_path}'.")
optimized_images_map = []
print("\n--- FAZA 1: OPTIMIZACIJA SLIK ---")
for filename in os.listdir(images_full_path):
file_path = os.path.join(images_full_path, filename)
# Preskoči podmape (kot je 'original') in datoteke, ki niso datoteke
if not os.path.isfile(file_path):
continue
name, ext = os.path.splitext(filename)
ext = ext.lower()
if filename in EXCLUDE_FILES_FROM_OPTIMIZATION:
print(f"- Preskakujem izključeno datoteko: '{filename}'")
continue
if ext in IMAGE_EXTENSIONS_TO_OPTIMIZE:
new_filename = f"{name}.webp"
new_file_path = os.path.join(images_full_path, new_filename)
# Preveri, če WebP verzija že obstaja in je novejša
if os.path.exists(new_file_path) and os.path.getmtime(new_file_path) > os.path.getmtime(file_path):
print(f"- WebP '{new_filename}' že obstaja in je posodobljen. Preskakujem optimizacijo.")
optimized_images_map.append({'old': filename, 'new': new_filename})
continue
if optimize_image(file_path, new_file_path, WEBP_QUALITY, MAX_IMAGE_DIMENSION, args.dry_run):
optimized_images_map.append({'old': filename, 'new': new_filename})
if not args.dry_run:
try:
shutil.move(file_path, os.path.join(original_images_full_path, filename))
print(f" Original '{filename}' premaknjen v '{ORIGINAL_IMAGES_SUBDIR_NAME}/'.")
except Exception as e:
print(f" NAPAKA pri premikanju '{filename}': {e}")
else:
print(f" DRY RUN: Original '{filename}' bi bil premaknjen v '{ORIGINAL_IMAGES_SUBDIR_NAME}/'.")
if not optimized_images_map:
print("\nNi bilo najdenih novih slik za optimizacijo.")
print("\n--- FAZA 2: POSODABLJANJE REFERENC V PROJEKTU ---")
files_to_scan = find_files_to_update(DIRECTORIES_TO_SCAN, DIRECTORIES_TO_EXCLUDE_FROM_SCAN)
if not files_to_scan:
print("Ni najdenih .html, .css ali .js datotek za pregled.")
else:
print(f"Najdenih {len(files_to_scan)} datotek za pregled...")
updated_files_count = 0
for file_path in files_to_scan:
file_was_updated = False
for img_info in optimized_images_map:
if update_file_references(file_path, img_info['old'], img_info['new'], args.dry_run):
file_was_updated = True
if file_was_updated:
updated_files_count += 1
print(f"\nPregledanih je bilo {len(files_to_scan)} datotek.")
print(f"Posodobljenih je bilo {updated_files_count} datotek.")
print("\n--- SKRIPTA JE ZAKLJUČILA Z DELOM ---")
if __name__ == "__main__":
main()"""
"./prestrukturiraj.py" :
"""
import os
import shutil
import re
def prestrukturiraj_spletno_stran():
"""
Skripta prestrukturira spletno stran tako, da vsako .html datoteko
(razen index.html v korenu) premakne v svojo mapo in jo preimenuje v index.html.
Na koncu posodobi vse povezave v vseh HTML datotekah.
"""
korenski_direktorij = '.'
datoteke_za_obdelavo = []
mapa_povezav = {}
# --- FAZA 1: Najdi vse .html datoteke, ki jih je treba premakniti ---
print("--- Faza 1: Iskanje HTML datotek za prestrukturiranje ---")
for pot, mape, datoteke in os.walk(korenski_direktorij):
# Izognemo se sistemskim in skritim mapam
if any(part in pot for part in ['.git', '.vscode', '__pycache__']):
continue
for datoteka in datoteke:
# Obdelamo samo .html datoteke, ki niso že index.html
if datoteka.endswith('.html') and datoteka != 'index.html':
ime_brez_koncnice = datoteka[:-5]
stara_pot = os.path.join(pot, datoteka)
# Posebna obravnava za "omeni.html", kot je bilo zahtevano
if ime_brez_koncnice == "omeni":
ime_nove_mape = "o-meni"
else:
ime_nove_mape = ime_brez_koncnice
nova_mapa_pot = os.path.join(pot, ime_nove_mape)
nova_datoteka_pot = os.path.join(nova_mapa_pot, 'index.html')
datoteke_za_obdelavo.append({
'stara_pot': stara_pot,
'nova_mapa_pot': nova_mapa_pot,
'nova_datoteka_pot': nova_datoteka_pot
})
# Shranimo preslikavo za kasnejšo zamenjavo povezav
mapa_povezav[datoteka] = ime_nove_mape + '/'
if not datoteke_za_obdelavo:
print("Ni datotek za prestrukturiranje. Postopek končan.")
return
# --- FAZA 2: Ustvari mape, premakni in preimenuj datoteke ---
print("\n--- Faza 2: Ustvarjanje map in prestavljanje datotek ---")
for info in datoteke_za_obdelavo:
stara_pot = info['stara_pot']
nova_mapa_pot = info['nova_mapa_pot']
nova_datoteka_pot = info['nova_datoteka_pot']
try:
os.makedirs(nova_mapa_pot, exist_ok=True)
print(f" -> Ustvarjena mapa: {nova_mapa_pot}")
shutil.move(stara_pot, nova_datoteka_pot)
print(f" -> Datoteka '{stara_pot}' uspešno prestavljena v '{nova_datoteka_pot}'")
except Exception as e:
print(f"NAPAKA pri prestavljanju '{stara_pot}': {e}")
# --- FAZA 3: Posodobi vse povezave v vseh HTML datotekah ---
print("\n--- Faza 3: Posodabljanje povezav v vseh HTML datotekah ---")
vse_html_datoteke = []
for pot, _, datoteke in os.walk(korenski_direktorij):
if any(part in pot for part in ['.git', '.vscode', '__pycache__']):
continue
for datoteka in datoteke:
if datoteka.endswith('.html'):
vse_html_datoteke.append(os.path.join(pot, datoteka))
for html_datoteka in vse_html_datoteke:
try:
with open(html_datoteka, 'r', encoding='utf-8') as f:
vsebina = f.read()
originalna_vsebina = vsebina
# Zamenjaj povezave na podlagi ustvarjene mape
for stara_datoteka, nova_pot in mapa_povezav.items():
# Regularni izraz, ki najde href="...stara_datoteka.html" in ga zamenja
vzorec = re.compile(f'href=(["\'])([^"\'#?]*?){re.escape(stara_datoteka)}(["\'])')
vsebina = vzorec.sub(f'href=\\1\\2{nova_pot}\\3', vsebina)
# Posebna obravnava za glavno datoteko index.html, da postane relativna pot "/"
vzorec_index = re.compile(f'href=(["\'])index.html(["\'])')
vsebina = vzorec_index.sub('href=\\1/\\2', vsebina)
if vsebina != originalna_vsebina:
with open(html_datoteka, 'w', encoding='utf-8') as f:
f.write(vsebina)
print(f" -> Posodobljene povezave v datoteki: {html_datoteka}")
except Exception as e:
print(f"NAPAKA pri posodabljanju povezav v '{html_datoteka}': {e}")
# Zaženi glavno funkcijo
if __name__ == "__main__":
prestrukturiraj_spletno_stran()
print("\nPrestrukturiranje spletne strani je končano.")"""
"./storitve/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Predstavitev ponudbe | Mag. Hermina Merc</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<!-- CSS Stylesheet -->
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="page-hero storitve-page-hero">
<div class="container">
<!-- Zunanji vsebnik za pozicioniranje slike -->
<div class="storitve-hero-image-wrapper animate-on-scroll">
<!-- Notranji vsebnik, ki ustvari kvadratno razmerje -->
<div class="storitve-hero-image-container">
<img src="/assets/images/morje-z-napisom.webp" alt="Morje z napisom Energy of Eternal Life">
</div>
</div>
<!-- Vsebnik za besedilo na desni strani -->
<div class="storitve-hero-text-content animate-on-scroll">
<h1 class="page-title">Predstavitev ponudbe</h1>
<p class="page-subtitle">Integralna celostna psihoterapija, zvočna gong terapija, globinsko psihofizično in energetsko sproščanje, psihološka priprava športnikov, strokovne psihološke delavnice in seminarji, tematska predavanja, integralni protistresni in proti izgorevanju psihološki program, poučevanje kundalini joge, shakti dance - yoga plesa, plesno gibalna praksa - terapevtski sprostitveni ples, specialne relaksacije (dihalne tehnike meditacija, umik v tišino), profesionalna supervizija, učna analiza (izkustvena psihoterapija kot učni proces za strokovnjake, ki delajo z ljudmi), psihoterapija za menedžerje in poslovneže, specialne ponudbe za termalna zdravilišča (po dogovoru).</p>
</div>
</div>
</section>
<section class="container">
<div class="services-grid">
<!-- 1. Integralna celostna psihoterapija -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/6A8DAA/FFFFFF/600x400.png?text=Integralna+celostna+psihoterapija" alt="Integralna celostna psihoterapija">
</div>
<div class="service-card-content">
<h3>Integralna celostna psihoterapija</h3>
<p>To je psihoterapija, osredotočena na celostno obravnavo posameznika, njegovih čustev, misli in telesnih stanj za doseganje notranjega ravnovesja.</p>
<a href="/storitve/integralna-celostna-psihoterapija/" class="service-card-link">Preberi več →</a>
</div>
</div>
<!-- 2. Terapija s plesom -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/B46A8E/FFFFFF/600x400.png?text=Terapija+s+plesom" alt="Terapija s plesom">
</div>
<div class="service-card-content">
<h3>Terapija s plesom</h3>
<p>Povezovanje psihoterapije z dinamičnim plesnim gibanjem za sproščanje blokad, izražanje čustev in ponovno vzpostavitev stika s telesom.</p>
<a href="/storitve/terapija-s-plesom/" class="service-card-link">Preberi več →</a>
</div>
</div>
<!-- 3. Psihoterapija za managerje -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/5E8B7E/FFFFFF/600x400.png?text=Psihoterapija+za+managerje" alt="Psihoterapija za managerje in vodstveni kader">
</div>
<div class="service-card-content">
<h3>Psihoterapija za managerje in vodstveni kader</h3>
<p>Specializirana podpora za posameznike na odgovornih delovnih mestih pri soočanju s stresom, izgorelostjo in iskanju profesionalnega ravnovesja.</p>
<a href="/storitve/psihoterapija-za-managerje/" class="service-card-link">Preberi več →</a>
</div>
</div>
<!-- 4. Supervizija -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/C2A370/FFFFFF/600x400.png?text=Razvojnointegrativna+supervizija" alt="Razvojno integrativna supervizija">
</div>
<div class="service-card-content">
<h3>Razvojno integrativna supervizija</h3>
<p>Strokovna podpora in svetovanje za strokovnjake, ki delajo z ljudmi, z namenom osebne in profesionalne rasti ter preprečevanja izgorelosti.</p>
<a href="/storitve/supervizija/" class="service-card-link">Preberi več →</a>
</div>
</div>
<!-- 5. Protistresni programi -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/8FA3A7/FFFFFF/600x400.png?text=Protistresni+programi" alt="Protistresni in proti psihofizičnemu izgorevanju programi">
</div>
<div class="service-card-content">
<h3>Protistresni in proti psihofizičnemu izgorevanju programi</h3>
<p>Programi psihofizičnega sproščanja, namenjeni revitalizaciji organizma, zmanjševanju napetosti in vzdrževanju dinamičnega življenjskega stila.</p>
<a href="/storitve/protistresni-programi/" class="service-card-link">Preberi več →</a>
</div>
</div>
<!-- 6. Kundalini joga -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/D08C60/FFFFFF/600x400.png?text=Poučevanje+Kundalini+joge" alt="Poučevanje Kundalini joge">
</div>
<div class="service-card-content">
<h3>Poučevanje Kundalini joge</h3>
<p>Vodena vadba za razvoj "pametnega popka, modrega srca in prazne glave" ter doživljanje lastne energije in notranjega prostora.</p>
<a href="/storitve/kundalini-joga/" class="service-card-link">Preberi več →</a>
</div>
</div>
<!-- 7. Zvočna terapija -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/707793/FFFFFF/600x400.png?text=Zvočna+terapija+z+gong+glasbili" alt="Zvočna terapija z gong glasbili">
</div>
<div class="service-card-content">
<h3>Zvočna terapija z gong glasbili</h3>
<p>Uporaba prvobitnega zvoka gonga za sproščanje čustev, raztapljanje strahov in aktivacijo notranje modrosti za samoozdravitev.</p>
<a href="/storitve/zvocna-terapija/" class="service-card-link">Preberi več →</a>
</div>
</div>
<!-- 8. Predavanja -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/93827F/FFFFFF/600x400.png?text=Predavanja" alt="Predavanja">
</div>
<div class="service-card-content">
<h3>Predavanja</h3>
<p>Tematska predavanja o psihoterapiji v praksi, namenjena poglobljenemu razumevanju procesov, metod in vloge psihoterapevta.</p>
<a href="/storitve/predavanja/" class="service-card-link">Preberi več →</a>
</div>
</div>
<!-- 9. Delavnice in seminarji -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/8B9E8A/FFFFFF/600x400.png?text=Izkustvene+psihološke+delavnice" alt="Izkustvene psihološke delavnice in seminarji">
</div>
<div class="service-card-content">
<h3>Izkustvene psihološke delavnice in seminarji</h3>
<p>Delavnice za osebnostni in profesionalni razvoj, ki z uporabo kreativnih medijev pomagajo pri predelavi izzivov in odkrivanju notranjih moči.</p>
<a href="/storitve/izkustvene-delavnice/" class="service-card-link">Preberi več →</a>
</div>
</div>
<!-- 10. Priprava športnikov -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/B96D6D/FFFFFF/600x400.png?text=Psihološka+priprava+športnikov" alt="Psihološka priprava športnikov">
</div>
<div class="service-card-content">
<h3>Psihološka priprava športnikov</h3>
<p>Specializirana pomoč športnikom pri doseganju mentalne trdnosti, obvladovanju pritiska in maksimiziranju njihovega tekmovalnega potenciala.</p>
<a href="/storitve/priprava-sportnikov/" class="service-card-link">Preberi več →</a>
</div>
</div>
<!-- 11. Shakti Dance -->
<div class="service-card animate-on-scroll">
<div class="service-card-image">
<img src="https://placehold.jp/38/A87CAE/FFFFFF/600x400.png?text=Shakti+Dance+-+Yoga+plesa" alt="Shakti Dance - Yoga plesa">
</div>
<div class="service-card-content">
<h3>Shakti Dance - Yoga plesa</h3>
<p>Nova disciplina joge in plesa, ki združuje jogijsko zavest z milino gibanja za zmanjšanje stresa, sproščanje in osvobajanje življenjske sile duše (Prana).</p>
<a href="/storitve/shakti-dance/" class="service-card-link">Preberi več →</a>
</div>
</div>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<!-- JavaScript -->
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/integralna-celostna-psihoterapija/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Integralna celostna psihoterapija | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css"> <!-- Pot je relativna na mapo višje -->
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<h1 class="page-title animate-on-scroll">Integralna celostna psihoterapija</h1>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<p>Dobro je vedeti, da je vse, kar se nam v življenju zgodi, zgolj učenje. Zato pri tem ne smemo biti preresni, saj resnost prinaša žalost. In potem pride jeza, saj je resen človek jezen na vsakogar.</p>
<p>Če želimo v življenju kaj narediti, če želimo svoje življenje osmisliti, se moramo prebuditi. Psihoterapija nam pomaga prebuditi sebe, začutiti sebe skozi občutek in globlje zavedanje. Ko zaupamo svojim občutjem, se začnemo spreminjati, preobražati, rasti.</p>
<p>Povedati pa je potrebno, da psihoterapija sama po sebi še ne pomaga, temveč le pripomore, da človek začne zdraviti samega sebe. Na njegovem potovanju do samega sebe in globljega zavedanja mu pomaga empatični sopotnik - psihoterapevt.</p>
<p>Glavni vzrok bolezni sodobnega človeka je prav gotovo strah, kamor spadajo tudi vsa negativna prepričanja, dvomi v samega sebe, obsojanje s strani drugih in samega sebe, vrednostne sodbe, ocenjevanje, preveč tuhtanja in razmišljanja.</p>
<p>Tako nam psihoterapija pomaga ozavestiti omejujoče vzorce in strahove, ki smo jim v svoji notranjosti nenehno izpostavljeni, tudi če se jih ne zavedamo. Ko jih ozavestimo, se jih lahko osvobodimo.</p>
<p>Odkrivanje samega sebe in svojega življenjskega sveta, soočanje z življenjskimi strahovi in iluzijami v sedanjosti, preteklosti in prihodnosti odpira človeku v procesu psihoterapije vedno nove perspektive, do katerih mu pomaga psihoterapevt z različnimi psihoterapevtskimi znanji.</p>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/izkustvene-delavnice/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- === POPRAVEK: Spremenjen naslov v zavihku === -->
<title>Izkustvene strokovne psihološke delavnice in seminarji | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<!-- === POPRAVEK: Spremenjen glavni naslov strani === -->
<h1 class="page-title animate-on-scroll">Izkustvene strokovne psihološke delavnice in seminarji</h1>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<p>Namenjeno za posameznike in skupine, pare in družine, za podjetja, zavode in organizacije, za vodstveni kader in time, za športnike in trenerje, ter tudi za specifične socialne subkulture, in za šole, tako osnovne kot srednje, višje, in univerze (vsebina in teme po dogovoru).</p>
<ul>
<li>
<strong>Enodnevne</strong> (lokacija po dogovoru),
</li>
<li>
<strong>Večdnevne</strong> (v naravnem okolju, proč od mestnega vrveža).
</li>
</ul>
<h3 class="section-title">Tematika in pristopi:</h3>
<!-- === POPRAVEK: Dopolnjen odstavek z novim besedilom === -->
<p>Predelava aktualnih obremenjujočih situacij, izzivov in problemov iz osebnega in profesionalnega življenja, ter tematiziranje sanj, ob uporabi kreativnih medijev kot so psihodrama, gibalna terapija, "prazni" stol, muzikoterapija, zvočne sprostitvene kopeli s pojočimi gongi, risanje, vodena miselna potovanja, magično ritualno pripovedovanje zgodb; spretnosti komuniciranja, kognitivno vedenjsko preoblikovanje neustreznih vzorcev razmišljanja, vedenja in motečih navad - razvad, poti odkrivanja in dotika z našimi čuti, odkrivanje lastnih notranjih moči in rezerv (virov), iskanje navdiha za prihodnost, specialne poživljajoče metode osebne psihofizične energetske sprostitve in relaksacije.</p>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Povprašajte o delavnicah</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/kundalini-joga/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Poučevanje Kundalini joge | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<h1 class="page-title animate-on-scroll">Poučevanje Kundalini joge</h1>
<!-- === POPRAVEK: Izbrisan stari podnaslov in dodan nov === -->
<p class="page-subtitle animate-on-scroll">
Kundalini joga<br>
Pranayama umetnost dihalnih tehnik
</p>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<p>Verjetno ste že slišali stari izrek, da so za uspeh česarkoli v življenju potrebne tri stvari: želja, disciplina in usmeritev. In seveda fizična vadba.</p>
<p>Z vadbo kundalini joge začenjamo razvijati to, kar sodobni ljudje imenujejo »pameten popek, modro srce, in prazna glava«. Te vaje omogočijo vsakomur popolnoma novo izkušnjo doživljanja svojega telesa in notranjega prostora, lastne energije in občutenja samega sebe.</p>
<p>Prakticiranje učenja kundalini joge sestavljajo vaje: telesne pozicije (asane), s specialnim dihanjem (pranayame); gibi rok, dlani in prstov (mudre), ki ponazarjajo pomen mantre; telesne mišične zapore (bande) za usmeritev energije; petje - chanting (mantre) za prenos notranje energije v zvoke; in meditacije, kar izvajamo združeno ali posamezno z namenom ustvarjanja specifičnega določenega učinka.</p>
<p>Set takšnih vaj učitelji kundalini yoge imenujemo krije. Po vsaki vaji je pomemben kratek počitek, da opazujemo in prepoznavamo notranje učinke in pretok prebujene energije v nas.</p>
<p>Kundalini joga, ki jo je utemeljil Jogi Bhajan, mojster in učitelj Hathe, Tantrične in Kundalini yoge, v temelju tako sestavljajo fizične dinamične asane, ki se prepletajo v koordinaciji z dihanjem in meditacijskimi vajami, z namenom povečevanja fleksibilnosti celotnega telesa in telesnih organov, psihofizičnega sproščanja, osredotočanja uma, in odpiranja energetskih kanalov v telesu, v smislu sproščanja napetosti in blokad. S tem usposabljamo telo in um, da prepoznata, sprejmeta in ponotranjita lastno subtilnejše gibanje, ki pomaga spodbuditi pretočnost energije prane v nas.</p>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/predavanja/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Predavanja | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<h1 class="page-title animate-on-scroll">Predavanja</h1>
<p class="page-subtitle animate-on-scroll">Vse kar dejansko želite izvedeti o psihoterapiji - s praktično pojasnitvijo.</p>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<h2 class="section-title">Osrednje predavanje: PSIHOTERAPIJA V PRAKSI</h2>
<h3 class="section-title">Teme:</h3>
<ul>
<li>Kaj je psihoterapija</li>
<li>Kdaj in kako vstopiti v psihoterapevtski proces</li>
<li>Nepoznavanje pomena psihoterapije pri posamezniku in v družbi</li>
<li>Vrsta psihoterapije</li>
<li>Razlika med psihologom - kliničnim psihologom - psihoterapevtom - psihiatrom</li>
<li>Kaj je dejansko osrednje delo psihoterapevta pri profesionalnem delu s klientom</li>
<li>Vzajemnost ciljev udeležencev v psihoterapevtskem procesu: klient - psihoterapevt</li>
<li>Izbira klienta med medikamentozno terapijo in/ali psihoterapijo kot obliko pomoči</li>
</ul>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/priprava-sportnikov/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Psihološka priprava športnikov | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<h1 class="page-title animate-on-scroll">Psihološka priprava športnikov</h1>
<!-- === POPRAVEK: Zamenjan podnaslov === -->
<p class="page-subtitle animate-on-scroll">Doseganje odličnosti in uspešnosti v športu z osebnostno in mentalno čvrstostjo in emocionalnim čustvenim ravnovesjem</p>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<p>Vrhunski šport zahteva ne le izjemno telesno pripravljenost, temveč tudi izjemno mentalno moč. Psihološka priprava je ključni del mozaika uspeha, ki športnikom pomaga obvladovati pritiske, ohranjati fokus, graditi samozavest in dosegati svoj maksimalni potencial, ko je to najpomembneje.</p>
<p>Pristop je individualno prilagojen vsakemu športniku in vključuje tehnike za:</p>
<ul>
<li>Upravljanje s tekmovalno anksioznostjo in stresom.</li>
<li>Postavljanje in doseganje realističnih, a ambicioznih ciljev.</li>
<li>Izboljšanje koncentracije in osredotočenosti.</li>
<li>Tehnike vizualizacije za izboljšanje izvedbe.</li>
<li>Gradnjo odpornosti po neuspehih in poškodbah.</li>
<li>Izboljšanje komunikacije znotraj ekipe in s trenerji.</li>
</ul>
<p><strong>Storitev se izvaja po dogovoru z zainteresiranimi posamezniki, klubi ali zvezami.</strong></p>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/protistresni-programi/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Protistresni programi | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<!-- === POPRAVEK: Spremenjen naslov === -->
<h1 class="page-title animate-on-scroll">Integralni psihološki protistresni in proti osebnostnemu izgorevanju psihološki programi psihofizičnega sproščanja</h1>
<p class="page-subtitle animate-on-scroll">Učinkovit način za revitalizacijo organizma in vzdrževanje dinamičnega življenjskega stila.</p>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<p>Namenjeni: ljudem vseh generacij; tako zdravim kot tistim, ki so se znašli v časovnem vrtincu sodobnega načina življenja in že čutijo na sebi težo napetosti (delajo in živijo »pod pritiskom«) in obremenitev, ki se lahko kažejo tudi v obliki psihosomatskih bolezenskih znakov.</p>
<p><strong>Psihološki sprostitveni energetski trening je učinkovit način za revitalizacijo človekovega organizma in pomaga vzdrževati dinamičen življenjski stil med napetostmi in zahtevami sodobnega življenja.</strong> Ker se navadimo na dobro počutje, ki nam ga nudijo mišično raztezanje, dihanje, sproščanje telesa in duha, se vse težje razvijajo kronične napetosti, ki so odgovorne za bolezenske težave.</p>
<p>S tem, da se sprostimo, kolikor mogoče globoko in pogostokrat, zelo koristimo svojemu zdravju. Napetosti in blokade v mišicah in duševnosti popustijo, naš imunski sistem se okrepi, tako da se počutimo in tudi izgledamo mnogo bolje. Sprostitveni psihofizični trening namreč preprečuje pretirano izčrpanost, in tako pripomore tudi k kvalitetnejšemu življenju in uspešnejšemu delu.</p>
<p>Strokovno vodena vadba sproščanja obsega sistem enostavnih, a strokovnih in izredno močnih vaj globokega mišičnega in psihičnega sproščanja, dihalne vaje, energetske poživljajoče vaje, vodeno vizualizacijo in meditacijo z glasbo, kar celovito uravnoteži in poživlja človeka na telesnem, čustvenem, razumskem in duhovnem nivoju.</p>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/psihoterapija-za-managerje/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Psihoterapija za Managerje | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<h1 class="page-title animate-on-scroll">Psihoterapija za managerje in vodstveni kader</h1>
<p class="page-subtitle animate-on-scroll">Za managerje, poslovneže, vodstveni kader in za ljudi na odgovornih delovnih mestih, in ki profesionalno sodelujejo z drugimi ljudmi.</p>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<p>Prepoznavate pri sebi, da se velikokrat pretirano čustveno odzovete na življenjske izzive in na ljudi okoli sebe? Ali pa, da z nervozno nestrpnostjo izkazujete nemir in impulzivno nasprotujete vsemu ter proti vsem izražate despotsko inteligenco na začudenje in zgražanje vaših bližnjih? Morebiti ste tudi že začeli prepoznavati svojo obsedenost z nekaterimi odločitvami, ki pa jih nikakor ne zmorete sprejeti in izvršiti, ker čutite, da vam tudi njihova uresničitev ne bo prinesla osebnega miru in zadovoljstva? Morda trenutno še prav dobro funkcionirate pod pritiskom in se ne zavedate, da vas poslovni stres dela vse bolj grobega, in da je samo še vprašanje časa, kdaj bo vaša energičnost prešla v nevarnost nekontroliranega izliva energije.</p>
<p>Bolezni in krize, ki jih preživlja vse večje število ljudi, so pogosto rezultat tega, da smo pozabili prisluhniti subtilnim ritmom našega notranjega bitja, naše duševnosti.</p>
<p>Med tipična zdravstvena obolenja sodobnih ljudi na vodilnih in vodstvenih odgovornih poklicnih položajih, ki bi radi iz neke vrste notranje »prisile«, ki jo čutijo, čim več - čim prej - čim bolje storili, ne spadajo samo bežne bolečine pri srcu, občutki pečenja in tesnobnosti v prsih in pridružene palpitacije, glavoboli, migrene in bolečine v hrbtu in vratu, vzdraženi želodec in občutki napihnjenosti, temveč tudi panični tesnobni napadi ter ponavljajoče se težave kot so kašelj, alergijske reakcije kože in dihal, nedoločene bolečine v čeljustih, preobčutljivo črevesje, pogostejše uriniranje, trepet (drget), spolna otopelost, nespečnost oziroma moten spanec, »prisilke« v obliki vsiljivih misli, ki se jih ni mogoče otresti, kronična izčrpanost ter depresivno razpoloženje.</p>
<p>Izpostavila bi še najrazličnejše strahove, tudi strahove pred vsakdanjostjo, enoličnostjo in notranjo praznino, pred navidezno nerešljivim problemom, neprijetnim sodelavcem ali življenjskim partnerjem ter strahove, vezane na vsakdanje navade, razvade, ki jih ljudje občutijo kot škodljive, a jih ne zmorejo preseči, razen s prisilnim odpovedovanjem, ki pa nima trajnejšega učinka.</p>
<p>Če ste začutili, da prihaja čas za neko vrsto vaše osebne transformacije, namesto dosedanjega prepuščanja iluzijam, da je z vami vse v najlepšem redu in/ ali da so za vaše stresne razmere krivi (samo) drugi; ter sebičnim sanjam in ugajanju samemu sebi; potem vam svetujem, da preprosto morate najti dovolj poguma, volje, inspiracije, odgovornosti in zavestnosti za lastne spremembe skozi ustvarjalni proces v integralni psihoterapiji.</p>
<p>In če boste z iskreno voljo, energijo in s pristno iskrivostjo ter vsaj kančkom radovednosti začeli delati na sebi in svojih notranjih zmožnostih v ustvarjalnem procesu integralne psihoterapije ter si tudi dovolili napredovanje v vaši preobrazbi, vam lahko kot vrhunski strokovnjak celovito pomagam k večjemu zavedanju pristnega življenjskega namena in plemenitenju lastnega življenja.</p>
<p>Vedite pa, da v kolikor že čutite to energijo za spremembe, ne želite pa odgovoriti na njo na način, ki bi bil za vas koristen in potreben, potem žal dovoljujete, da vaše življenje še naprej ostane takšno, kot je.</p>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/shakti-dance/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shakti Dance - Yoga plesa | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<h1 class="page-title animate-on-scroll">Shakti Dance - Yoga plesa</h1>
<p class="page-subtitle animate-on-scroll">Nova disciplina joge in plesa, ki je plod spoznanj in prakse ustanoviteljice Sare Avtar Olivier.</p>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<p>Plesanje je ena najbolj izraznih oblik delovanja, skozi katero se lahko izrazi in manifestira utrip naše duše. S plesom in z glasbo lahko najplemeniteje izrazimo najglobje duševne izkušnje. Ples in glasba sta za človeka načina, s katerima lahko senzibilno in pristno izrazi samega sebe skozi svojo osebno telesno vibracijo.</p>
<p>V sodobnem času pretežno površinskega in (pre)hitrega življenjskega stila lahko vsakomur predstavlja izziv lastno iskanje novega odnosa do življenja in samoregeneracije. Prav zato je potrebno spoznati in prakticirati načine, ki povečujejo in ojačajo našo življenjsko energijo, spodbujati senzibilnost in notranjo moč zavedanja ter s tem povečati vzdržljivost našega živčnega sistema.</p>
<!-- === POPRAVEK: Dodan prvi sklop novega besedila === -->
<p>Da bi se izognili telesnemu in duševnemu izgorevanju je bistvenega pomena, da razvijemo sposobnost zavestne kontrole našega uma in da znamo učinkovito spreminjati stanja zavesti. Razviti nevtralen, meditativen um skozi jogo je ključ do sposobnosti prestavljanja zavesti iz enega stanja v drugega in do odpiranja prave poti življenja.</p>
<p>Prav tako je pomembno, da najdemo učinkovito metodo, s katero lahko spreminjamo našo notranjo energijo. Takšna resnično odlično izpopolnjena metoda in tehnika se nahaja tako v Kundalini Yogi, kot jo je učil Yogi Bhajan, kot v Shakti Dance, ustanoviteljice Sare Avtar Olivier.</p>
<h3 class="section-title">Kaj je Shakti Dance?</h3>
<p>Shakti Dance je Yoga Plesa, nova disciplina joge in plesa, ki je plod spoznanj in prakse ustanoviteljice Sare Avtar Olivier. Temelji na Kundalini Yogi, kot jo je učil Yogi Bhajan, in na spoznanjih, ki jih je avtorsko razvila Sara Avtar Olivier. Ponuja veselo, milo in zdravo jogijsko prakso plesa. V ples vnaša jogijsko zavest z namenom odpiranja in širjenja ozaveščenosti v stanju jogijske združitve.</p>
<p>Shakti Dance deluje na razvijanju notranje harmonije in miline v gibanju. Zmanjšuje stres in napetost, sprošča in osvobaja telesne, duševne in subtilne zadržanosti in zavrtosti ter istočasno spodbuja in osvobaja življenjske sile duše (Prana).</p>
<!-- === POPRAVEK: Dodan drugi sklop novega besedila === -->
<p>Shakti Dance nežno odpira in uravnoveša subtilne življenjske tokove (meridiani/nadiji) v telesu tako, da harmonično združuje telesne asane, različne plesne sloge, dihalne tehnike, ritmično koordinacijo, zbranost pozornost, in mantre.</p>
<p>Da bi razvili milino in mehkobo gibov, ki so značilnost svobodnega pretoka Duha v našem telesu, uporablja Shakti Dance spoznanja iz jogijske filozofije. Ta spoznanja prebujajo in aktivirajo univerzalne principe harmoničnega gibanja. Naravna dinamika gibov in telesna spretnost, ki se razvijejo s pomočjo teh principov pomagata, da se poveča naša moč in lahkotnost gibanja ter da se izostri senzibilnost za inteligentne gibalne vzorce, ki prihajajo iz naše notranjosti skozi Prana- Shakti.</p>
<p>Opis posamezne praktične vadbe Shakti dance joge plesa (im. SD class), ki jo sestavlja osem v gibanje integriranih jogijsko plesnih faz (cit. po avtorici Sari Avtar):</p>
<p>Kot prvo se telo in um uglasita z Duhom. Za to se uporabljajo “mantre” in “mudre”, ki povežejo posameznika s subtilno modrostjo duše in odpirajo varen meditativni prostor delovanja. Sledi niz Shakti raztezanj, to je vrsta nežnih vaj za odpiranje pranskega telesa, ki se izvajajo na tleh. Vaje so niz cikličnih, fluidnih, s pravilnim dihanjem povezanih asan, ki sproščajo napetost, povečajo prožnost in obseg gibanja, ki sproži možnost, da izkusimo graciozno fluidnost gibov. Postopoma dihanje prevzame vodilno vlogo in nam pomaga ohranjati meditativni tok gibanja.</p>
<p>V nadaljevanju sledi niz energetskih, ponavljajočih se vaj, ki jih izvajamo stoje, kjer z enakomernim in usklajenim dihanjem odpiramo pransko telo in čakre. V tej fazi napajamo vitalnost. S širjenjem gibalnih vzorcev spodbujamo in nežno in skrbno uravnovešamo energetski spekter.</p>
<p>Ko je pransko telo svobodno in se prosto giblje, se notranja modrost duše, ki jo navdihuje Shakti, začne razpletati. Ne voden, svobodni ples prevzame ustvarjalni zagon in ima prosto pot pri izražanju samega sebe in svojega ustvarjalnega vzgiba. Večja ozaveščenost avre omogoča prijetno raziskovanje človekovega notranjega in zunanjega prostora. Po sprostitvi lahko sledi koreografija na podlagi mantrične glasbe, niz ponavljajočih se zaporedij, kjer se člani skupine porazdele v geometrične oblike. To služi usklajevanju energije posameznika in skupine. Ob tem se tke skupinsko energetsko polje in vzpodbuja meditativni um. Krovni trenutek predstavlja skupinska meditacija, kjer lahko posameznik v popolnosti uživa občutek izpolnjenosti, ki mu ga daje zadovoljstvo samoizražanja in se povsem potopi v Notranji Vir.</p>
<p>Ob zaključku se ustvari avrični ščit in se s tem uravnovesi notranje in zunanje svetove.</p>
<p>Enostavneje povedano: Na začetku posamezne Shakti dance vadbe (SD class), je torej posameznikova pozornost usmerjena v zunanje telesno izražanje (Shakti), kasneje, kot končni cilj, pa se pozornost usmeri navznoter, v stanje umirjene meditacije (Shiva). Zadoščenju, ki nam ga da samoizražanje skozi gib, se pridruži ozaveščenost, ki je osvobojena in dovolj prazna, da se lahko spoji s tihim življenjem popolnega mirovanja Duha. Končni cilj joge plesa Shakti Dance pa je odpreti, očistiti, razviti in razširiti energetsko telo (pransko telo) z namenom, da se omogoči prosti pretok Shakti; in seveda povezovanje z Duhom.</p>
<p>
<small>Op.: pričujoči tekst je privzet in citiran iz slovenskega prevoda po viru: Shakti Dance TT Manual Level 1, avtorice Sare Avtar Kaur Olivier.</small>
</p>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/supervizija/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Razvojno integrativna supervizija | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<h1 class="page-title animate-on-scroll">Razvojno integrativna supervizija</h1>
<p class="page-subtitle animate-on-scroll">Strokovna podpora za rast, razvoj in preprečevanje izgorelosti v poklicih profesionalne klinične in psihosocialne stroke nudenja pomoči.</p>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<p>Profesionalna supervizija je metoda, ki strokovnjaka vzpodbuja k spoznavanju samega sebe, svojih pristopov pri delu in profesionalnega delovanja, pri kateri se strokovnjak uči iz svojih izkušenj, iz uvidevanja in širjenja različnih perspektiv pogleda na strokovne probleme, dileme in možnosti.</p>
<p>Tako je supervizija na eni strani strokovna podpora posamezniku pri prenašanju obremenitev pri odgovornem strokovnem delu (preprečevanje otopelosti in izgorevanja), na drugi strani pa deluje na razvijanje in izpopolnjevanje njegove profesionalne kompetentnosti, pri čemer strokovnjak oblikuje osebni odnos »osebno noto« do svojega profesionalnega poklica in delovanja.</p>
<p>Dejstvo je, da so strokovni delavci in sodelavci v poklicih, kjer se iz dneva v dan soočajo s hudim človeškim trpljenjem, boleznimi, psihosocialnimi stiskami, materialnim pomanjkanjem, bolj izpostavljeni tistim dejavnikom, ki lahko ogrozijo njihovo lastno psihofizično ravnovesje ali celo zdravje (problem stresa in/ali nato izgorelosti).</p>
<p>Marsikdo, marsikdaj doživlja, da so zahteve, ki jih ima pred seboj, kopičijo in ga začenja razjedati dvom ali bo zmogel.</p>
<p>Zaradi stalne izpostavljenosti obremenjujočim situacijam, prihaja do večjega absorbiranja težav, s katerimi se soočajo uporabniki.</p>
<p>Reakcijo na stres, ki je vedno individualna, to je, pri vsakem od nas različna, določa interakcija med mnogimi dejavniki: med osebnostjo, stresorji v delovnem okolju, stresorji v osebnem življenju strokovnjaka in podporo znotraj in zunaj delovnega okolja.</p>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/terapija-s-plesom/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Terapija s plesom | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<h1 class="page-title animate-on-scroll">Terapija s plesom v povezavi z integralno psihoterapijo</h1>
<p class="service-tagline animate-on-scroll">Združuje vrhunsko znanje integralne psihoterapije z dinamičnim plesnim gibanjem in senzibilnim telesnim izražanjem.</p>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<p>TERAPIJA S PLESOM je plesanje spontanih izvornih ritmov izražanja gibanja telesa, ki se odvija skozi inspirirajoči ples, ko senzibilno, a z živostjo premikamo svoje telo. To je plesanje, kjer ne obstajajo predsodki, kritiziranje ega, ocenjevanje, in kjer začutimo telo, dih, srce, um, dušo in duha kot vibriranje celovite energije.</p>
<p>Kot integralni psihoterapevt TERAPIJO S PLESOM izvajam v povezanosti z INTEGRALNO PSIHOTERAPIJO, ki človeku sicer že sama s svojim celostnim strokovnim pristopom samostojno ali pa v povezavi s senzibilnim terapevtskim plesnim gibanjem odpira »notranja« vrata do globljega občutenja osvobajanja spontanosti in dinamičnega ravnotežja pri samem sebi in v življenju.</p>
<p>V svoji vsakodnevni praksi kot integralni psihoterapevt prepoznavam, da ljudje namesto da bi raziskali in spoznali sebe intimno in spiritualno, mnogi ugasnejo svoja čutila in si nadenejo oklep (miselni, čustveni, mišični), ker jim je spoznavanje sebe v globino svojega telesa in duha zastrašujoče in preveč intenzivno.</p>
<p>Vaše duševno stanje se namreč zrcali v telesu. Morda veste ali pa tudi (še) ne, da je v telesu zapisana vaša celotna osebna zgodovina, od začetka spočetja do danes.</p>
<p>Ta vrsta terapevtskega plesa pomaga osebi, da se iz »glave« (pretirano razmišljanje, tuhtanje, zaskrbljenost, dvomi v vse in v vsakogar) spusti v telo (premikanje telesa in gibanje v plesanju) ter ga oživi in osvobodi. Telo namreč predstavlja mesto, v katerem se spajajo energije. In ker se skozi ples začne telo bolj svobodno premikati, se premaknejo tudi vaša čustva, zablokiranost v vašem doživljanju in razmišljanju. Vse to lahko skozi gibanje v plesanju prepoznavate, osvobajate, »greste skozi« ter izplešete.</p>
<p>Ta ples kot terapevtsko prakticiranje skozi spontanost v gibanju ob podpori integralne psihoterapije vam lahko pomaga postati bolj pristno odprti od znotraj navzven (ne pa nasprotno, kar je običajno v sodobnem svetu), bolj intuitivni, oživljeni, ekstatični, celoviti, zdravi.</p>
<p>Morebiti so tudi vas spomini iz preteklosti zasidrali tako močno, da vam otežujejo pomik naprej.</p>
<p>Ali razumete, da je vašo pozornost ta moja ponudba pritegnila prav iz razloga, da bi odkopali in izkoreninili pretekle spomine kot vir neugodnih občutij v sedanjosti?</p>
<p>Če se vam namreč pogosto dogaja, da si »zakopljete« težke spomine in se s tem zaščitite pred psihično bolečino ali stisko, da se ne bi spominjali teh mučnih trenutkov, ko vas življenje preizkuša do skrajne meje, vam predlagam, da zberete pogum ter zaupanje, in si v integralni psihoterapiji razkrijete te lekcije, da se boste lahko premaknili naprej z zavedanjem…</p>
<p>Kot integralni psihoterapevt želim poudariti, da je za vsakega človeka posebej pomembno to, da se lahko v kombinaciji integralne psihoterapije in terapije s plesom (zaradi edinstvene priložnosti, ki vam jo kot strokovnjak nudim, da povežete obe) vrača, osvobodi ter »iz pleše« vsa tista svoja življenjska razdobja (na primer, obdobje nežnega otroštva ali pozne pubertete ali zgodnje odraslosti), kjer se je čutil (ali se še počuti) »nenahranjenega«, neizživetega, ali pa je celo doživel travmatske izkušnje, ki vplivajo na njegovo sedanje življenje, četudi jih je »izbrisal« iz spomina.</p>
<p>Vedite, da v tem plesnem gibanju in v kombinaciji z integralno psihoterapijo obstaja resnično mnogo pomoči za razrešitev, in če vam jo kdo preprečuje, ste to edino vi sami s svojimi iluzijami in strahovi pred snemanjem lastnih mask in oklepov.</p>
<p>Kot integralni psihoterapevt vam lahko v plesno terapevtskem gibanju ob podpori integralne psihoterapije strokovno pomagam in vas vodim, da z zaupanjem in radostjo opazujete svoje telo in globlje razumete, kaj vas uči telo, ter pristno spoznavate tudi svojo dušo.</p>
<p>V idealnem primeru se boste (o)zdravili in si ustvarili prostor večjega udobja in veselja, ker se boste naučili popolneje biti v svojem telesu in ker boste imeli novo dimenzijo lastnega, in to ne samo telesnega, temveč celovitega izražanja samega sebe.</p>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./storitve/zvocna-terapija/index.html" :
"""
<!DOCTYPE html>
<html lang="sl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Zvočna terapija z gong glasbili | Mag. Hermina Merc</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body class="subpage">
<header class="main-header">
<div class="header-container">
<div class="logo">
<a href="/">Psihoterapevt, vrhunski strokovnjak</a>
</div>
<nav class="main-nav" id="main-navigation">
<ul>
<li><a href="/o-meni/">O meni</a></li>
<li><a href="/kaj-je-psihoterapija/">Kaj je psihoterapija</a></li>
<li><a href="/storitve/">Predstavitev ponudbe</a></li>
<li><a href="/cenik/">Cenik storitev</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/kontakt/" class="nav-cta">Kontakt in naročanje</a></li>
</ul>
</nav>
<button
class="mobile-nav-toggle"
aria-controls="main-navigation"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger"></span>
</button>
</div>
</header>
<main class="page-main-content">
<section class="service-hero">
<div class="container">
<h1 class="page-title animate-on-scroll">Zvočna terapija z gong glasbili</h1>
<p class="page-subtitle animate-on-scroll">Zakaj kot integralna psihoterapevtka uporabljam zvočno terapijo z gongi?</p>
</div>
</section>
<section class="container service-content-wrapper">
<div class="animate-on-scroll">
<p>Ker je zvok gonga prvobiten zvok (zvok Univerzuma OM), prebuja v ljudeh prvobitna čustva, tudi strahove in nesigurnost. Čudovito pri igranju gonga pa je, da jih tudi raztaplja. S pomočjo zvoka se sprostijo in čistijo čustva, vozlički, osebnost, preko zvoka aktiviramo notranjo modrost, podporo in moč za samoozdravitev, in tako sami sebe zdravimo.</p>
<p>Da bi spoznali življenje, moramo najprej spoznati sebe, da bi se lahko odpravili na potovanje v življenje, se moramo najprej odpraviti vase - potopiti se dovolj globoko vase, do točke veličastne notranje tišine in miru, ki je prav učinek zvoka gonga. Zvoke gonga uporabljamo za odpiranje srca, npr. če smo čustveno v neravnovesju, ima gong to zmožnost, da očisti osebnost in zjasni misli.</p>
<p>Zvoki gonga človeku omogočijo na 1. nivoju sprostitev in zdravljenje duše, na 2. nivoju odpiranje lastni ustvarjalnosti in intuiciji ter notranjemu navdihu, na 3. nivoju pa omogočajo duhovne izkušnje in rast.</p>
<p>Terapevtsko zdravljenje z gongi se opira na odprtost človeka k celovitosti: na željo, da opustimo, vse kar prizadene, nas blokira ali zavira - npr. napačne zamisli, negativna čustva in razmišljanja, nepriporočljiv življenjski slog - ter tako razširimo svoj spekter dovzetnosti in doživljanja z novimi idejami, izkustvi in prednostmi - torej se pogumno (čeprav s strahom) odpremo iskanju novih perspektiv za svoje življenje. Zdravljenje je namreč komunikacija, in zvok je v svoji univerzalnosti popolna komunikacija.</p>
</div>
<div class="content-cta animate-on-scroll">
<a href="/kontakt/" class="cta-button">Kontakt in naročanje</a>
</div>
</section>
</main>
<footer class="main-footer-bar">
<p>
© <span id="current-year"></span> Mag. Hermina Merc. Vse pravice
pridržane.
</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem; margin-bottom: 0.25rem;">
Copy right za vse fotografije in ves tekst na tej internetni strani:
Hermina Merc
</p>
<p style="font-size: 0.8rem; margin-bottom: 0;">
Nobena fotografija in noben del teksta ni dovoljeno uporabljati brez
pisnega dovoljenja avtorice te spletne strani.
</p>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>"""
"./style.css" :
"""
/* --- :ROOT - CSS SPREMENLJIVKE --- */
:root {
--font-heading: 'Playfair Display', serif;
--font-body: 'Montserrat', sans-serif;
--color-text: #2c3e50; /* Temna, skoraj črna-modra */
--color-background: #fdfdfd;
--color-primary-accent: #4682B4; /* Jekleno modra - profesionalna in umirjena */
--color-primary-accent-dark: #3a6a92;
--color-white: #ffffff;
--color-border: #e0e0e0;
--spacing-xs: 0.25rem;
--spacing-s: 0.5rem;
--spacing-m: 1rem;
--spacing-l: 2rem;
--spacing-xl: 4rem;
--shadow-light: 0 4px 6px rgba(0, 0, 0, 0.05);
--shadow-medium: 0 8px 24px rgba(0, 0, 0, 0.1);
--transition-fast: 0.2s ease-in-out;
--transition-medium: 0.5s ease-in-out;
}
/* --- OSNOVNI STILI IN RESET --- */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
font-size: 16px;
overflow-x: hidden;
}
body {
font-family: var(--font-body);
color: var(--color-text);
background-color: var(--color-background);
line-height: 1.7;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-x: hidden;
}
/* POSEBEN STIL ZA DOMAČO STRAN, DA PREPREČI DRSENJE STRANI */
body.homepage {
overflow: hidden;
}
h1, h2, h3 {
font-family: var(--font-heading);
font-weight: 700;
line-height: 1.2;
margin-bottom: var(--spacing-m);
}
p {
margin-bottom: var(--spacing-m);
}
a {
color: var(--color-primary-accent);
text-decoration: none;
transition: color var(--transition-fast);
}
a:hover {
color: var(--color-primary-accent-dark);
}
/* --- GLAVA IN NAVIGACIJA --- */
.main-header {
background-color: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
box-shadow: var(--shadow-light);
border-bottom: 1px solid var(--color-border);
position: relative; /* Potrebno za z-index mobilnega menija */
z-index: 1000;
}
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-m) var(--spacing-l);
max-width: 1600px; /* Ohranimo širino iz prve datoteke za dober desktop izgled */
margin: 0 auto;
}
.logo a {
font-family: var(--font-heading);
font-weight: 800;
font-size: 1.2rem;
color: var(--color-text);
letter-spacing: 0.5px;
}
/* MOBILNA NAVIGACIJA: Osnovni stili */
.main-nav {
display: none; /* Privzeto skrito za mobilne naprave */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(253, 253, 253, 0.98);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
flex-direction: column;
justify-content: center;
align-items: center;
transform: translateY(-100%);
transition: transform var(--transition-medium);
}
.main-nav.open { /* Uporabljamo razred 'open' za aktivacijo mobilnega menija */
display: flex;
transform: translateY(0);
}
.main-nav ul {
list-style: none;
display: flex;
flex-direction: column;
gap: 1.5rem;
align-items: center;
text-align: center;
padding: 0; /* Dodano padding: 0 iz druge datoteke */
}
.main-nav a {
color: var(--color-text);
font-weight: 600;
font-size: 1.2rem;
padding: var(--spacing-s) 0;
position: relative;
letter-spacing: 0.5px;
}
.main-nav a::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 2px;
background-color: var(--color-primary-accent);
transition: width var(--transition-fast);
}
.main-nav a:hover::after,
.main-nav a.active::after {
width: 100%;
}
.main-nav a.nav-cta {
background-color: var(--color-primary-accent);
color: var(--color-white);
padding: var(--spacing-s) var(--spacing-m);
border-radius: 50px;
transition: background-color var(--transition-fast), transform var(--transition-fast);
}
.main-nav a.nav-cta:hover {
background-color: var(--color-primary-accent-dark);
color: var(--color-white);
transform: translateY(-2px);
}
.main-nav a.nav-cta:hover::after {
width: 0;
}
/* --- MOBILNA NAVIGACIJA (HAMBURGER) --- */
.mobile-nav-toggle {
display: block; /* Hamburger gumb je privzeto viden na mobilnih napravah */
background: none;
border: none;
cursor: pointer;
z-index: 1001; /* Višji od menija, da je vedno na vrhu */
padding: var(--spacing-s);
position: relative;
}
.hamburger {
display: block;
position: relative;
width: 24px;
height: 2px;
background: var(--color-text);
transition: all 0.25s ease-in-out;
}
.hamburger::before, .hamburger::after {
content: '';
position: absolute;
left: 0;
width: 100%;
height: 2px;
background: var(--color-text);
transition: all 0.25s ease-in-out;
}
.hamburger::before { top: -8px; }
.hamburger::after { bottom: -8px; }
/* Hamburger se spremeni v X, ko je meni odprt (CSS dodan v media query) */
/* ================================================= */
/* === NOVI STILI ZA DRSNIK NA DOMAČI STRANI === */
/* ================================================= */
.slider {
position: relative;
max-width: 1200px;
margin: var(--spacing-l) auto;
background: var(--color-white);
padding: var(--spacing-l);
border-radius: 1rem;
overflow: hidden;
box-shadow: var(--shadow-medium);
}
.slide {
display: none;
}
.slide.active {
display: block;
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.slide-content {
display: flex;
align-items: center;
gap: var(--spacing-xl);
}
.slide-image {
flex: 1 1 50%;
}
.slide-image img {
width: 100%;
height: auto;
display: block;
border-radius: 0.5rem; /* Rahlo zaobljeni robovi na sliki */
}
.slide-text {
flex: 1 1 50%;
}
.slide-text h2 {
font-size: clamp(1.8rem, 4vw, 2.5rem);
color: var(--color-primary-accent);
margin-bottom: var(--spacing-m);
}
.slide-text p {
margin-bottom: var(--spacing-m);
}
.cta {
display: inline-block;
background-color: var(--color-primary-accent);
color: var(--color-white);
padding: var(--spacing-m) var(--spacing-l);
border-radius: 50px;
font-weight: 700;
margin-top: var(--spacing-m);
transition: background-color var(--transition-fast), transform var(--transition-fast);
box-shadow: var(--shadow-light);
}
.cta:hover,
.cta:focus {
background-color: var(--color-primary-accent-dark);
transform: translateY(-3px);
color: var(--color-white);
}
.nav-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(255, 255, 255, 0.8);
border: 1px solid var(--color-border);
width: 44px;
height: 44px;
font-size: 1.5rem;
border-radius: 50%;
cursor: pointer;
transition: all var(--transition-fast);
z-index: 10;
user-select: none;
color: var(--color-text);
box-shadow: var(--shadow-light);
}
.nav-btn:hover:not(:disabled) {
background: var(--color-white);
transform: translateY(-50%) scale(1.05);
}
.nav-btn.prev {
left: var(--spacing-m);
}
.nav-btn.next {
right: var(--spacing-m);
}
.nav-btn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
/* --- NOGA --- */
.main-footer-bar {
padding: var(--spacing-l) var(--spacing-l);
text-align: center;
font-size: 0.9rem;
color: #777;
background-color: #f1f1f1;
}
body:not(.homepage) .main-footer-bar {
margin-top: var(--spacing-xl);
}
/* =============================================== */
/* === STILI ZA PODSTRANI (OSTANEJO NESPREMENJENI) === */
/* =============================================== */
.page-main-content {
padding-top: var(--spacing-xl);
padding-bottom: var(--spacing-xl);
min-height: calc(100vh - 80px - 150px);
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 0 var(--spacing-l);
}
.page-title {
font-size: clamp(2.5rem, 6vw, 4rem);
text-align: center;
margin-bottom: var(--spacing-xl);
color: var(--color-primary-accent);
}
.section-title {
font-size: clamp(1.5rem, 4vw, 2rem);
margin-top: var(--spacing-l);
margin-bottom: var(--spacing-m);
color: var(--color-text);
border-left: 4px solid var(--color-primary-accent);
padding-left: var(--spacing-m);
}
.intro-text {
font-size: 1.25rem;
font-style: italic;
font-weight: 500;
line-height: 1.6;
margin-bottom: var(--spacing-l);
color: #555;
}
.about-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
align-items: flex-start;
}
.about-image {
width: 100%;
max-width: 400px;
margin: 0 auto;
position: static;
}
.about-image img {
width: 100%;
height: auto;
border-radius: 10px;
box-shadow: var(--shadow-medium);
}
.animate-on-scroll {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
}
.animate-on-scroll.is-visible {
opacity: 1;
transform: translateY(0);
}
.image-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
margin-bottom: var(--spacing-xl);
}
.grid-image {
width: 100%;
min-height: 250px;
background-size: cover;
background-position: center;
border-radius: 10px;
box-shadow: var(--shadow-medium);
transition: transform var(--transition-medium), box-shadow var(--transition-medium);
}
.grid-image:hover {
transform: scale(1.03);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
}
.page-subtitle {
font-size: clamp(1.1rem, 3vw, 1.4rem);
text-align: center;
max-width: 800px;
margin: 0 auto var(--spacing-xl) auto;
color: #555;
}
.text-section {
margin-bottom: var(--spacing-l);
}
.highlight-quote {
margin: var(--spacing-l) auto;
padding: var(--spacing-l);
border-left: 5px solid var(--color-primary-accent);
background-color: rgba(70, 130, 180, 0.05);
border-radius: 0 8px 8px 0;
}
.highlight-quote p {
font-size: 1.1rem;
font-style: italic;
font-weight: 500;
margin-bottom: var(--spacing-m);
}
.highlight-quote cite {
display: block;
text-align: right;
font-style: normal;
font-weight: 600;
}
.concluding-statement {
text-align: center;
padding: var(--spacing-l);
margin: var(--spacing-xl) 0;
border: 1px solid var(--color-border);
border-radius: 8px;
background-color: var(--color-white);
box-shadow: var(--shadow-light);
}
.concluding-statement p {
margin-bottom: 0;
font-size: 1.1rem;
line-height: 1.8;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.content-cta {
text-align: center;
margin-top: var(--spacing-xl);
}
.page-hero {
padding: var(--spacing-l) 0;
text-align: center;
background-color: rgba(70, 130, 180, 0.05);
margin-bottom: var(--spacing-xl);
}
.page-hero .page-title {
margin-bottom: var(--spacing-m);
}
.page-hero .page-subtitle {
font-size: 1.1rem;
max-width: 700px;
margin: 0 auto;
color: #555;
font-style: normal;
}
.services-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
}
.service-card {
background: var(--color-white);
border-radius: 10px;
box-shadow: var(--shadow-light);
overflow: hidden;
display: flex;
flex-direction: column;
transition: transform var(--transition-fast), box-shadow var(--transition-fast);
border-top: 4px solid var(--color-primary-accent);
}
.service-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-medium);
}
.service-card-image img {
width: 100%;
height: 200px;
object-fit: cover;
display: block;
transition: transform var(--transition-medium);
}
.service-card:hover .service-card-image img {
transform: scale(1.05);
}
.service-card-content {
padding: var(--spacing-l) 1.5rem 1.5rem 1.5rem;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.service-card h3 {
font-size: 1.25rem;
color: var(--color-text);
margin-bottom: var(--spacing-m);
}
.service-card p {
font-size: 0.95rem;
color: #555;
flex-grow: 1;
margin-bottom: var(--spacing-m);
}
.service-card-link {
font-weight: 600;
color: var(--color-primary-accent);
align-self: flex-start;
position: relative;
padding-bottom: var(--spacing-xs);
}
.service-card-link::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0%;
height: 2px;
background-color: var(--color-primary-accent);
transition: width var(--transition-fast);
}
.service-card-link:hover::after {
width: 100%;
}
.pricing-accordion {
max-width: 900px;
margin: 0 auto;
}
.accordion-item {
background: var(--color-white);
border: 1px solid var(--color-border);
border-radius: 8px;
margin-bottom: var(--spacing-m);
box-shadow: var(--shadow-light);
transition: box-shadow var(--transition-fast);
}
.accordion-item:hover {
box-shadow: var(--shadow-medium);
}
.accordion-header {
width: 100%;
background: transparent;
border: none;
padding: 1.25rem 1.5rem;
font-family: var(--font-heading);
font-size: 1.25rem;
font-weight: 700;
color: var(--color-text);
text-align: left;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
.accordion-icon {
display: inline-block;
width: 24px;
height: 24px;
position: relative;
transition: transform var(--transition-fast);
}
.accordion-icon::before, .accordion-icon::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 16px;
height: 2px;
background-color: var(--color-primary-accent);
transform: translate(-50%, -50%);
}
.accordion-icon::after { transform: translate(-50%, -50%) rotate(90deg); }
.accordion-item.active .accordion-icon { transform: rotate(135deg); }
.accordion-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.4s ease-out, padding 0.4s ease-out;
}
.accordion-item.active .accordion-content {
padding-bottom: 1.5rem;
}
.price-list { list-style: none; padding: 0 1.5rem; }
.price-item {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: var(--spacing-xs);
padding: var(--spacing-m) 0;
border-bottom: 1px solid var(--color-border);
}
.price-item:last-child { border-bottom: none; }
.service-name, .service-price {
flex-basis: 100%;
text-align: left;
}
.service-name { color: #444; }
.service-price { font-weight: 700; font-size: 1.1rem; color: var(--color-primary-accent); }
.special-pricing-note {
max-width: 900px;
margin: var(--spacing-xl) auto 0 auto;
padding: var(--spacing-l);
text-align: center;
background-color: rgba(70, 130, 180, 0.1);
border: 2px dashed var(--color-primary-accent);
border-radius: 8px;
}
.special-pricing-note h3 { margin-bottom: var(--spacing-s); }
.special-pricing-note p { margin: 0; font-size: 1.2rem; font-weight: 600; }
.blog-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-l);
}
.blog-card {
background: var(--color-white);
border-radius: 10px;
box-shadow: var(--shadow-light);
overflow: hidden;
transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
.blog-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-medium);
}
.card-link-wrapper { display: block; color: inherit; text-decoration: none; }
.blog-card-image { overflow: hidden; }
.blog-card-image img { width: 100%; height: 220px; object-fit: cover; display: block; transition: transform var(--transition-medium); }
.blog-card:hover .blog-card-image img { transform: scale(1.05); }
.blog-card-content { padding: 1.5rem; }
.blog-card-title { font-size: 1.3rem; color: var(--color-text); margin-bottom: var(--spacing-m); line-height: 1.3; }
.blog-card-excerpt { font-size: 0.95rem; color: #555; margin-bottom: var(--spacing-m); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.blog-card-link { font-weight: 600; color: var(--color-primary-accent); position: relative; padding-bottom: var(--spacing-xs); display: inline-block; }
.blog-card-link::after { content: ''; position: absolute; bottom: 0; left: 0; width: 0%; height: 2px; background-color: var(--color-primary-accent); transition: width var(--transition-fast); }
.blog-card:hover .blog-card-link::after { width: 100%; }
.contact-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-xl);
}
.contact-details {
background-color: rgba(221, 226, 229, 0.2);
padding: var(--spacing-l);
border-radius: 8px;
}
.contact-info-item { margin-bottom: 1.5rem; }
.contact-info-item .info-label { display: block; font-size: 0.9rem; font-weight: 600; color: #777; margin-bottom: var(--spacing-xs); }
.contact-info-item .info-data { font-size: 1.1rem; margin: 0; }
.contact-info-item .info-data a { word-break: break-all; }
.map-placeholder { width: 100%; height: 300px; border-radius: 8px; overflow: hidden; margin-top: var(--spacing-l); background-color: #e9e9e9; box-shadow: inset 0 2px 4px rgba(0,0,0,0.06); }
.map-placeholder iframe { width: 100%; height: 100%; border: 0; }
.contact-form-wrapper { background: var(--color-white); padding: var(--spacing-l); border-radius: 8px; box-shadow: var(--shadow-light); }
.contact-form .form-group { margin-bottom: 1.5rem; }
.contact-form label { display: block; margin-bottom: var(--spacing-s); font-weight: 600; }
.contact-form input[type="text"], .contact-form input[type="email"], .contact-form textarea { width: 100%; padding: 0.8rem 1rem; border: 1px solid var(--color-border); border-radius: 5px; font-family: var(--font-body); font-size: 1rem; transition: border-color var(--transition-fast), box-shadow var(--transition-fast); }
.contact-form input[type="text"]:focus, .contact-form input[type="email"]:focus, .contact-form textarea:focus { outline: none; border-color: var(--color-primary-accent); box-shadow: 0 0 0 3px rgba(70, 130, 180, 0.2); }
.contact-form textarea { resize: vertical; min-height: 120px; }
.contact-form .cta-button { width: 100%; border: none; cursor: pointer; }
.form-message {
margin-top: var(--spacing-m);
padding: var(--spacing-m);
border-radius: 5px;
text-align: center;
font-weight: 600;
transition: opacity 0.3s ease-in-out, max-height 0.3s ease-in-out, margin 0.3s ease-in-out, padding 0.3s ease-in-out;
opacity: 0;
max-height: 0;
overflow: hidden;
padding-top: 0;
padding-bottom: 0;
margin-top: 0;
}
.form-message.visible {
opacity: 1;
max-height: 100px;
padding-top: var(--spacing-m);
padding-bottom: var(--spacing-m);
margin-top: var(--spacing-m);
}
.form-message.success {
background-color: rgba(70, 180, 130, 0.1);
color: #3a926a;
border: 1px solid #46B482;
}
.form-message.error {
background-color: rgba(180, 70, 70, 0.1);
color: #b44646;
border: 1px solid #b44646;
}
.service-hero { padding: var(--spacing-xl) 0; text-align: center; background-color: #f7f9fa; border-bottom: 1px solid var(--color-border); }
.service-hero .page-title { color: var(--color-text); }
.service-content-wrapper { max-width: 800px; margin: var(--spacing-xl) auto 0 auto; }
.service-content-wrapper .section-title { margin-top: var(--spacing-xl); }
.service-content-wrapper p { font-size: 1.05rem; line-height: 1.8; }
.service-content-wrapper strong { color: var(--color-primary-accent-dark); }
.service-tagline { font-size: 1.1rem; font-weight: 600; text-align: center; text-transform: uppercase; letter-spacing: 1px; margin: var(--spacing-xl) 0; color: var(--color-primary-accent); }
.article-header { text-align: center; margin-bottom: var(--spacing-xl); }
.article-header .page-title { margin-bottom: var(--spacing-m); }
.article-meta { font-size: 0.9rem; color: #777; margin-bottom: var(--spacing-l); }
.article-hero-image { width: 100%; height: 250px; background-size: cover; background-position: center; border-radius: 10px; margin-bottom: var(--spacing-xl); box-shadow: var(--shadow-medium); }
.article-content { max-width: 750px; margin: 0 auto; }
.article-content h2, .article-content h3 { margin-top: var(--spacing-l); margin-bottom: var(--spacing-m); font-size: 1.5rem; color: var(--color-primary-accent-dark); }
.article-content p { font-size: 1.05rem; line-height: 1.8; margin-bottom: 1.5rem; }
.article-content ul { list-style-position: inside; padding-left: 1rem; margin-bottom: 1.5rem; }
.article-content li { margin-bottom: 0.75rem; }
.article-content blockquote { margin: var(--spacing-l) 0; padding-left: var(--spacing-l); border-left: 4px solid var(--color-primary-accent); font-style: italic; font-size: 1.2rem; color: #555; }
.article-content strong { color: var(--color-text); }
.back-to-blog { display: inline-block; margin-top: var(--spacing-xl); font-weight: 600; }
/* --- MEDIA QUERIES --- */
@media (max-width: 991px) {
.mobile-nav-toggle {
display: block; /* Prikaže hamburger gumb na mobilnih napravah */
}
/* KODA ZA AKTIVACIJO MOBILNEGA MENIJA IN HAMBURGER IKONE NA MOBILNIH NAPRAVAH */
/* Hamburger se spremeni v X, ko je meni odprt (glede na razred 'open' na toggle gumbu) */
.mobile-nav-toggle.open .hamburger {
background: transparent;
}
.mobile-nav-toggle.open .hamburger::before {
transform: rotate(45deg);
top: 0;
}
.mobile-nav-toggle.open .hamburger::after {
transform: rotate(-45deg);
bottom: 0;
}
}
@media (max-width: 768px) {
/* Spremembe za tablice in manjše naprave */
.slide-content {
flex-direction: column;
text-align: center;
}
.slide-text h2 {
font-size: 1.8rem;
}
/* Povečajte število stolpcev za manjše naprave, če so bile omejene na 1fr */
.image-grid, .services-grid, .blog-grid, .contact-grid {
grid-template-columns: 1fr; /* Ohranite 1 stolpec, če je primerno za mobilne naprave */
}
.grid-image { min-height: 250px; }
.article-hero-image { height: 250px; }
.price-item {
flex-direction: column;
align-items: flex-start;
}
.service-price {
text-align: left;
margin-top: var(--spacing-xs);
}
}
@media (min-width: 768px) {
/* Stili za večje tablice */
.image-grid { grid-template-columns: 1fr 1fr; }
.services-grid { grid-template-columns: repeat(2, 1fr); }
.blog-grid { grid-template-columns: repeat(2, 1fr); }
.grid-image { min-height: 350px; }
.article-hero-image { height: 350px; }
.price-item {
flex-direction: row;
align-items: center;
gap: 0;
}
.service-name { flex-basis: 70%; padding-right: var(--spacing-m); }
.service-price { flex-basis: 30%; text-align: right; }
}
@media (min-width: 992px) {
/* Stili za namizje */
.mobile-nav-toggle {
display: none; /* Skrije hamburger gumb na namizju */
}
.main-nav {
display: flex; /* Prikaže navigacijo kot flex kontejner */
position: static; /* Odstrani fiksno pozicioniranje */
height: auto;
width: auto;
background-color: transparent;
backdrop-filter: none; /* Odstrani zameglitev na namizju */
-webkit-backdrop-filter: none; /* Odstrani zameglitev na namizju */
transform: none; /* Odstrani transformacijo */
flex-direction: row; /* Elementi menija v vrsto */
align-items: center;
}
.main-nav ul {
flex-direction: row; /* Elementi seznama v vrsto */
gap: 1.8rem;
}
.main-nav a {
font-size: 0.9rem; /* Manjša pisava za namizje */
padding: var(--spacing-s) 0; /* Dodano padding */
}
.main-nav a.nav-cta {
padding: var(--spacing-s) var(--spacing-m);
}
.about-grid {
grid-template-columns: 1fr 2fr;
gap: var(--spacing-xl);
}
.about-image {
max-width: 100%;
position: sticky;
top: calc(var(--spacing-l) + 80px); /* Odmik + višina glave */
}
.services-grid, .blog-grid {
grid-template-columns: repeat(3, 1fr);
gap: var(--spacing-xl);
}
.contact-grid {
grid-template-columns: 1fr 1fr;
align-items: flex-start;
}
.article-hero-image {
height: 400px;
}
}"""
"./update_footers.py" :
"""
import os
import re
def update_all_footers_from_template():
"""
Robustna skripta, ki vsebino iz 'layouts/footer.html' prebere in z njo
prepiše VSE <footer>...</footer> sekcije v vseh ostalih .html datotekah v projektu.
Eksplicitno izključi datoteki header.html in footer.html.
"""
project_root = '.'
footer_template_path = os.path.join(project_root, 'layouts', 'footer.html')
# --- KORAK 1: Preberi vsebino nove noge iz datoteke s predlogo ---
try:
with open(footer_template_path, 'r', encoding='utf-8') as f:
new_footer_content = f.read().strip()
print(f"Uspešno prebrana vsebina noge iz: {footer_template_path}")
except FileNotFoundError:
print(f"NAPAKA: Datoteka s predlogo noge ni bila najdena na poti: {footer_template_path}")
print("Prepričajte se, da datoteka obstaja in da skripto zaganjate iz korenske mape projekta ('hermina-merc').")
return
except Exception as e:
print(f"NAPAKA pri branju datoteke s predlogo noge: {e}")
return
# --- KORAK 2: Pripravi seznam datotek za izključitev ---
# Uporabimo os.path.normpath za zanesljivo primerjavo poti ne glede na OS (npr. / vs \)
excluded_files = [
os.path.normpath(footer_template_path),
os.path.normpath(os.path.join(project_root, 'layouts', 'header.html'))
]
print(f"\nDatoteki, ki bosta preskočeni (ker sta predlogi): {excluded_files}")
# --- KORAK 3: Pripravi robusten regularni izraz ---
# Ta vzorec bo našel katerokoli <footer> oznako, ne glede na atribute, in vso vsebino do </footer>
footer_pattern = re.compile(r'<footer.*?</footer', re.DOTALL | re.IGNORECASE)
# --- KORAK 4: Pojdi skozi vse datoteke in posodobi noge ---
print("\nZačenjam posodabljanje nog v HTML datotekah...")
updated_files_count = 0
skipped_files_count = 0
for root, dirs, files in os.walk(project_root):
# Izključimo mape, ki jih ne želimo pregledovati
dirs[:] = [d for d in dirs if d not in ['.git', '.vscode', '__pycache__']]
for filename in files:
if filename.endswith(".html"):
filepath = os.path.normpath(os.path.join(root, filename))
# PREVERI, ALI JE DATOTEKA NA SEZNAMU ZA IZKLJUČITEV
if filepath in excluded_files:
continue # Tiho preskoči predloge
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
original_content = content
# Zamenjaj obstoječo nogo z novo
updated_content, num_replacements = footer_pattern.subn(new_footer_content, content)
if num_replacements > 0:
# Preverimo, ali je dejansko prišlo do spremembe v vsebini
if updated_content != content:
with open(filepath, 'w', encoding='utf-8') as f:
f.write(updated_content)
print(f" [OK] Uspešno posodobljena noga v: {filepath}")
updated_files_count += 1
else:
print(f" [INFO] Noga najdena, vendar je že posodobljena v: {filepath}")
skipped_files_count += 1
else:
print(f" [POZOR] Noga za zamenjavo ni bila najdena v (preskočeno): {filepath}")
skipped_files_count += 1
except Exception as e:
print(f" [NAPAKA] Pri obdelavi datoteke {filepath}: {e}")
print("\n-------------------------------------------")
print("Posodabljanje je končano.")
print(f"Dejansko posodobljenih datotek: {updated_files_count}")
print(f"Preskočenih, že posodobljenih ali datotek brez noge: {skipped_files_count}")
print("-------------------------------------------")
# Zaženemo glavno funkcijo
if __name__ == "__main__":
update_all_footers_from_template()"""
"./update_headers.py" :
"""
import os
import re
def update_all_headers_from_template():
"""
Robustna skripta, ki vsebino iz 'layouts/header.html' prebere in z njo
prepiše VSE <header>...</header> sekcije v vseh ostalih .html datotekah v projektu.
Eksplicitno izključi datoteki header.html in footer.html.
"""
project_root = '.'
header_template_path = os.path.join(project_root, 'layouts', 'header.html')
# --- KORAK 1: Preberi vsebino nove glave iz datoteke s predlogo ---
try:
with open(header_template_path, 'r', encoding='utf-8') as f:
new_header_content = f.read().strip()
print(f"Uspešno prebrana vsebina glave iz: {header_template_path}")
except FileNotFoundError:
print(f"NAPAKA: Datoteka s predlogo glave ni bila najdena na poti: {header_template_path}")
print("Prepričajte se, da datoteka obstaja in da skripto zaganjate iz korenske mape projekta ('hermina-merc').")
return
except Exception as e:
print(f"NAPAKA pri branju datoteke s predlogo glave: {e}")
return
# --- KORAK 2: Pripravi seznam datotek za izključitev ---
# Uporabimo os.path.normpath za zanesljivo primerjavo poti ne glede na OS (npr. / vs \)
excluded_files = [
os.path.normpath(header_template_path),
os.path.normpath(os.path.join(project_root, 'layouts', 'footer.html'))
]
print(f"\nDatoteki, ki bosta preskočeni (ker sta predlogi): {excluded_files}")
# --- KORAK 3: Pripravi robusten regularni izraz ---
# Ta vzorec bo našel katerokoli <header> oznako, ne glede na atribute, in vso vsebino do </header>
header_pattern = re.compile(r'<header.*?</header>', re.DOTALL | re.IGNORECASE)
# --- KORAK 4: Pojdi skozi vse datoteke in posodobi glave ---
print("\nZačenjam posodabljanje glav v HTML datotekah...")
updated_files_count = 0
skipped_files_count = 0
for root, dirs, files in os.walk(project_root):
# Izključimo mape, ki jih ne želimo pregledovati
dirs[:] = [d for d in dirs if d not in ['.git', '.vscode', '__pycache__']]
for filename in files:
if filename.endswith(".html"):
filepath = os.path.normpath(os.path.join(root, filename))
# PREVERI, ALI JE DATOTEKA NA SEZNAMU ZA IZKLJUČITEV
if filepath in excluded_files:
continue # Tiho preskoči predloge
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
original_content = content
# Zamenjaj obstoječo glavo z novo
updated_content, num_replacements = header_pattern.subn(new_header_content, content)
if num_replacements > 0:
# Preverimo, ali je dejansko prišlo do spremembe v vsebini
if updated_content != content:
with open(filepath, 'w', encoding='utf-8') as f:
f.write(updated_content)
print(f" [OK] Uspešno posodobljena glava v: {filepath}")
updated_files_count += 1
else:
print(f" [INFO] Glava najdena, vendar je že posodobljena v: {filepath}")
skipped_files_count += 1
else:
print(f" [POZOR] Glava za zamenjavo ni bila najdena v (preskočeno): {filepath}")
skipped_files_count += 1
except Exception as e:
print(f" [NAPAKA] Pri obdelavi datoteke {filepath}: {e}")
print("\n-------------------------------------------")
print("Posodabljanje je končano.")
print(f"Dejansko posodobljenih datotek: {updated_files_count}")
print(f"Preskočenih, že posodobljenih ali datotek brez glave: {skipped_files_count}")
print("-------------------------------------------")
# Zaženemo glavno funkcijo
if __name__ == "__main__":
update_all_headers_from_template()"""